码迷,mamicode.com
首页 > 其他好文 > 详细

【codevs1225】八数码难题

时间:2017-10-14 22:30:37      阅读:157      评论:0      收藏:0      [点我收藏+]

标签:blog   opera   重要   ++   ccf   wap   queue   reg   print   

为了做这个题,我足足花了一个晚自习,才处理好所有的细节问题,太琐碎了

现在复习知识的同时,也会穿插上一些曾经学过但是了解不深的问题,比如a*

a*最重要的就是通过估价函数来大大优化搜索,估价函数是整个a*的灵魂,通过估价函数,可以省去大量的不必要的状态,是一个非常高效的算法。

其他话都写在代码里了,考初赛考的都快虚脱了╮(╯▽╰)╭辣鸡ccf,居然连页脚下方的几几年初赛都写错了,出的题目简直爆炸,今年复赛怕不是药丸

#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#define ri register int
const int mod=100003;
using namespace std;
bool flag[100010];
int ans,e[10][2],fx[4]={-1,0,1,0},fy[4]={0,1,0,-1};
struct in
{
    int mmp[4][4];//地图 
    int ha,rx,ry,as,mn,ca;//hash值,0的坐标,当前状态步数,以及状态被压成串 
    bool operator <(const in &a)const
    {
        return mn+as>a.mn+a.as;//估价函数g(i)是所有点与答案当中该点所在位置的曼哈顿距离之和 
    }
}st,ed;
priority_queue<in>qwq;
inline void hash(in &x)//求hash值,用于去重 
{
    int re=1;
    for(ri i=1;i<=3;i++)
        for(ri j=1;j<=3;j++)
            re=(re*26+x.mmp[i][j])%mod;
    x.ha=re%mod;
    return;
}
inline void chu(in &a,int x)//提前预处理好状态的估价函数,0所在的位置和hash值 
{
    a.ca=x,a.mn=0;
    int mo=100000000,shu=0;
    for(ri i=1;i<=9;i++)
    {
        shu=x/mo,a.mmp[(i-1)/3+1][i-(i-1)/3*3]=shu,x=x-x/mo*mo;
        a.mn+=abs((i-1)/3+1-e[shu][0])+abs(i-(i-1)/3*3-e[shu][1]);
        if(shu==0)
            a.rx=(i-1)/3+1,a.ry=i-(i-1)/3*3;
        mo/=10;
    }
    hash(a);
}
inline void ya(in &a)//将状态压缩成串 
{
    a.ca=0;
    for(ri i=1;i<=3;i++)
        for(ri j=1;j<=3;j++)
            a.ca=a.ca*10+a.mmp[i][j];
}
int n;
inline void bfs()//a* 
{
    while(!qwq.empty())
    {
        in qaq=qwq.top(),to;
        qwq.pop();
        if(qaq.ha==ed.ha)
        {
            ans=qaq.as;return;
        }
        to.as=qaq.as+1;
        for(ri i=0;i<4;i++)
        {
            to.rx=qaq.rx+fx[i],to.ry=qaq.ry+fy[i];
            if(to.rx<1||to.rx>3||to.ry<1||to.ry>3)
                continue;
            for(int i=1;i<=3;i++)
                for(int j=1;j<=3;j++)
                    to.mmp[i][j]=qaq.mmp[i][j];
            swap(to.mmp[to.rx][to.ry],to.mmp[qaq.rx][qaq.ry]);
            ya(to);
            chu(to,to.ca);
            if(!flag[to.ha])
                flag[to.ha]=1,qwq.push(to);
            swap(to.mmp[to.rx][to.ry],to.mmp[qaq.rx][qaq.ry]); 
        }
    }
}
int main()
{
    scanf("%d",&n);
    int m=100000000,shu=0,n1=123804765;
    for(int i=1;i<=9;i++)
    {
        shu=n1/m;
        e[shu][0]=(i-1)/3+1,e[shu][1]=i-(i-1)/3*3;//预处理好答案中的每种数字所在位置,便于一会求估价函数 
        n1=n1-n1/m*m,m/=10;
    }
    chu(st,n),chu(ed,123804765);//对这两个状态进行预处理,做好加入队列的准备 
    ya(st),ya(ed);//把状态压成个串,便于下面处理 
    qwq.push(st);
    bfs();
    printf("%d",ans);
}

 

【codevs1225】八数码难题

标签:blog   opera   重要   ++   ccf   wap   queue   reg   print   

原文地址:http://www.cnblogs.com/Loi-dfkdsmbd/p/7668689.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!