hdu 1043 八数码问题-A*搜索

来源:互联网 发布:网络教育本科第二学位 编辑:程序博客网 时间:2024/06/05 13:27

http://acm.hdu.edu.cn/showproblem.php?pid=1043


题意。。不再赘述,和小时候玩的玩具很像。


思路:今天人生终于完整了。。。

 来一个普通的A*搜索的思路。。。(感觉会不会倒着打表更快?)

所谓A*搜索个人理解就是对于BFS的一个优先级队列优化。。。至于用什么作为关键字就是一个F(F=H+G) 

H是估价函数,表示距离答案还有大约多少,越近H越高。。G是已花代价。。当然对于这个题目G并没有什么用,因为我们并不求最优,所以不如直接去直接以H作为关键字。


对于本题,和最终答案越一样那么就越应该先搜索,所以将9个数字的和本来应该在的位置的曼哈顿距离加起来就可以判断是不是更接近目标了。。

所以我们就可以设计一个看起来还不错的H函数。。。


有了估价函数就很愉快的A*啦


代码:

#include <bits/stdc++.h>using namespace std;const int dis[12] = {1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800};int tmp[10];char s[10];const int maxn=1e5*4;int arr[10];int vis[maxn];int last[maxn+10];int how[maxn+10];int ans=-1;int Cantor(int x, int len){    int c=0;    while(x){        tmp[c++]=x%10;        x/=10;    }    int resl = 1;    for(int i = 0; i < len; i++){        int counts = 0;        for(int k = i + 1; k < len; k++){            if(tmp[i] > tmp[k]){                counts++;            }        }        resl = resl + dis[len-i-1] * counts;    }    return resl;}int tran(int x,int h){    int c=0,ret=0,idx=0;;    while(x){        tmp[c++]=x%10;        if(tmp[c-1]==9) idx=c-1;        x/=10;    }    if(h==0){        if(idx<3) return -1;        else swap(tmp[idx],tmp[idx-3]);    }    else if(h==1){        if(idx%3==2) return -1;        else swap(tmp[idx],tmp[idx+1]);    }    else if(h==2){        if(idx>5) return -1;        else swap(tmp[idx],tmp[idx+3]);    }    else if(h==3){        if(idx%3==0) return -1;        else swap(tmp[idx],tmp[idx-1]);    }    for(int i=0,j=1;i<9;i++,j*=10) ret+=tmp[i]*j;    return ret;}int val(int x){    int c=0,ret=0;    while(x){        tmp[c++]=x%10;        ret+=abs((c-1)%3-(tmp[c-1]-1)%3)+abs((c-1)/3-(tmp[c-1]-1)/3);        x/=10;    }    return -ret;}struct node{    int val,num,id;    node(){};    node(int a,int b,int c):val(a),num(b),id(c){};};bool operator <(const node &a,const node &b){    return a.val<b.val;}bool Astar(){    memset(vis,0,sizeof(vis));    memset(last,-1,sizeof(last));    priority_queue<node> P;    int x=0,cnt=0;    for(int i=0,j=1;i<9;i++,j*=10) x+=arr[i]*j;    P.push(node(0,x,cnt++));    vis[Cantor(x,9)]=1;    while(!P.empty()){        node t=P.top();        P.pop();        ans=t.id;        if(t.num==987654321) return true;        if(cnt>2000) return false;        for(int i=0;i<4;i++){            int x=tran(t.num,i);            if(x!=-1&&vis[Cantor(x,9)]==0){                vis[Cantor(x,9)]=1;                last[cnt]=t.id;                how[cnt]=i;                P.push(node(val(x),x,cnt++));            }        }    }    return false;}char re[maxn];void pr(int x){    int c=0;    while(x!=0){        if(how[x]==0) re[c++]='u';        else if(how[x]==1) re[c++]='r';        else if(how[x]==2) re[c++]='d';        else if(how[x]==3) re[c++]='l';        x=last[x];    }    for(int i=c-1;i>=0;i--) printf("%c",re[i]);    puts("");}int main(){    while(cin>>s[0]>>s[1]>>s[2]>>s[3]>>s[4]>>s[5]>>s[6]>>s[7]>>s[8]){        for(int i=0;i<9;i++){            if(s[i]=='x') arr[i]=9;            else arr[i]=(int)(s[i]-'0');        }        if(Astar()){            //cout<<"ANS"<<ans<<endl;            pr(ans);        }        else{            puts("unsolvable");        }    }    return 0;}

0 0