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
- POJ 1077 Eight 八数码问题 A*
- poj 1077 Eight A*解八数码问题
- POJ 1077 Eight A*算法 八数码问题
- POJ 1077 Eight 八数码+A* -
- POJ 1077 Eight(BFS八数码问题)
- POJ 1077 Eight, 八数码问题
- Poj 1077 Eight 八数码问题 (搜索)
- POJ 1077 Eight 八数码问题 BFS
- POJ 1077 Eight && HDU 1043 Eight 八数码问题(A*算法)
- 1077 Eight 八数码问题
- POJ 1077 Eight 八数码 A*搜索算法
- POJ 1077 Eight(八数码A*+IDA*)
- poj 1077--Eight(八数码问题,BFS,A*,全排列的哈希)
- 搜索 ( 八数码问题详解:BFS,A*,IDA* )——Eight ( POJ 1077 )
- HDU 1043 / POJ 1077 Eight(八数码问题)
- poj 1077 Eight(经典八数码问题:bfs/Dbfs)
- POJ 1077 Eight 八数码问题[康托展开 + BFS]
- POJ 1077 Eight(bfs八数码问题)
- 编程之美---求N!的二进制表示中最低位1的位置
- 多线程的同步
- 音效codec芯片解决方案
- tcmalloc安装及使用
- 关于smallest eigenvector的理解
- poj 1077 Eight A*解八数码问题
- DeleteObject()
- LeetCode217:Contains Duplicate
- 第12周项目-阅读程序
- 安卓开机 重启 自启动程序 亲测可用
- 第11周项目2摩托车继承自行车和机动车
- Shell脚本之awk详解
- shell工程代码行数统计
- ios开发必备10款第三方类库