poj 1077 Eight A*解八数码问题

来源:互联网 发布:印度山地师 知乎 编辑:程序博客网 时间:2024/06/06 07:52

题意:

经典的八数码问题。

分析:

搜索算法的区别是如何重排open表,关键是如何编码状态和定义状态的值。对搜索过程中任意状态s,A*算法以g(s)+h(s)重排open表,也就是说g(s)+h(s)是排列open中状态的依据,其中g(s)是初始状态到s的消耗,h(s)是s到目标状态的估计。我重排open用的是c++的优先队列,扩展状态s得到新的状态ns,如果ns没访问过则直接将ns及其节点加入open。如果ns已经访问过(在open或close中),则更新ns的g(s)和h(s),由于无法直接在优先队列中进行更新,所以需要在外部用全局数组记录各个状态的g值,当某个状态的g值要改变时重新加入包含这个状态的节点,这样有冗余但不影响正确性,也是优先队列优化dijkstra算法的方法。关于启发函数h(s),h(s)越大则占g(s)+h(s)的比重越大,程序的速度也越快,当h(s)总小于实际到最终状态的消耗时,算法是能确定找到最优解的,否则能找到解但不一定能找到最优解(总消耗最少)。这题数据有问题,3*h(s)当启发函数是不能保证找到走过步数(消耗)最小的解的。

代码:

//poj 1077//sep9#include <iostream>#include <queue>#include <string> using namespace std;const int maxN=500000;const int aim=46233;int fac[]={1,1,2,6,24,120,720,5040,40320};int vis[maxN],g[maxN];int dirx[]={0,0,-1,1};int diry[]={-1,1,0,0};int goal_x[]={0,0,0,1,1,1,2,2};int goal_y[]={0,1,2,0,1,2,0,1};char word[8]="lrud";struct NODE{int s[9];int loc; //location of '0'int status;//cantor valueint f;//f=g+hstring path;bool operator <(const NODE &a) const{return f>a.f;}};priority_queue<NODE> open;string path;int cantor(int s[]){int sum=0;for(int i=0;i<9;++i){int cnt=0;for(int j=i+1;j<9;++j)if(s[i]>s[j])++cnt;sum+=cnt*fac[9-i-1];}return sum;}int h(int s[]){int sum=0;for(int i=0;i<3;++i)for(int j=0;j<3;++j){int k=i*3+j;if(s[k]!=9)sum+=abs(i-goal_x[s[k]-1])+abs(j-goal_y[s[k]-1]);}return sum;}int a_star(NODE start){memset(vis,0,sizeof(vis));while(!open.empty()) open.pop();NODE cur,nxt;open.push(start);vis[start.status]=1;while(!open.empty()){cur=open.top();open.pop();if(cur.status==aim){path=cur.path;return 1;}int x=cur.loc/3;int y=cur.loc%3;for(int i=0;i<4;++i){int tx=x+dirx[i];int ty=y+diry[i];if(tx<0||tx>=3||ty<0||ty>=3)continue;nxt=cur;nxt.loc=tx*3+ty;nxt.s[cur.loc]=nxt.s[nxt.loc];nxt.s[nxt.loc]=0;nxt.status=cantor(nxt.s);if(vis[nxt.status]==0){//0:not visited 1:in colse or openvis[nxt.status]=1;g[nxt.status]=g[cur.status]+1;nxt.f=g[nxt.status]+3*h(nxt.s);//h>h* can not always found the best solution,but can find a solution nxt.path=nxt.path+word[i];open.push(nxt);}/*else if(vis[nxt.status]==1&&g[cur.status]+1<g[nxt.status]){//bfs dis[i][j]==1  ==> g[cur]+1>=g[nxt] //nxt.f=nxt.f-g[nxt.status]+g[cur.status]+1;//update nxt.status //g[nxt.status]=g[cur.status]+1; //nxt.path=nxt.path+word[i]; //open.push(nxt);}*/}vis[cur.status]=1;}return 0;}int main(){char tmp[4];NODE ncur;for(int i=0;i<9;++i){scanf("%s",tmp);if(tmp[0]=='x'){ncur.s[i]=0;ncur.loc=i;}elsencur.s[i]=tmp[0]-'0';}ncur.status=cantor(ncur.s);g[ncur.status]=0;ncur.f=h(ncur.s);if(a_star(ncur))cout<<path;elseputs("unsolvable");return 0;} 


0 0
原创粉丝点击