POJ 1077 Eight 八数码问题 A*
2014-11-26 19:27
381 查看
题意:经典的八数码问题。
思路:我们这里用A*搜索来解决问题。
在A*算法中,我们定义一个h函数表示当前状态到目标需要的至少的步数。这样,在搜索的过程中,我们取出可能更接近目标的状态进行扩展,所以能更快的接近目标。
而对于这道题,定义h函数为每个数字到正确的位置,如果直接移动所需要的步数。可以看到,h函数是实际步数的下界,这个在A*中是十分重要的。
思路:我们这里用A*搜索来解决问题。
在A*算法中,我们定义一个h函数表示当前状态到目标需要的至少的步数。这样,在搜索的过程中,我们取出可能更接近目标的状态进行扩展,所以能更快的接近目标。
而对于这道题,定义h函数为每个数字到正确的位置,如果直接移动所需要的步数。可以看到,h函数是实际步数的下界,这个在A*中是十分重要的。
#include <cstdio> #include <algorithm> #include <cstring> #include <queue> using namespace std; const int MAX = 400010; int dx[] = {0,0,-1,1}; int dy[] = {1,-1,0,0}; char dir[] = {'r','l','u','d'}; int pos[][2] = {0,0,0,0,0,1,0,2,1,0,1,1,1,2,2,0,2,1}; int fact[20],d[MAX],fa[MAX],path[MAX]; bool vis[MAX]; void init() { fact[0] = 1; for(int i = 1; i < 9; ++i) fact[i] = fact[i-1] * i; } struct node{ int s[9]; int d,h,v; node(){} node(int t[9]){ d = 0; memcpy(s,t,sizeof(t)); } bool operator < (const node & rhs) const{ return d + h > rhs.d + rhs.h; } void cantor(){ v = 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++; v += fact[8 - i] * cnt; } } void hstar(){ h = 0; for(int i = 0; i < 3; ++i){ for(int j = 0; j < 3; ++j){ int z = 3 * i + j; int x = s[z]; h += abs(pos[x][0] - i) + abs(pos[x][1] - j); } } } }; node st; priority_queue<node> Q; bool Astar() { while(!Q.empty()) Q.pop(); Q.push(st);vis[st.v] = true; while(!Q.empty()){ node t = Q.top();Q.pop(); if(t.v == 46233) return true; for(int i = 0; i < 9; ++i) if(t.s[i] == 0){ int x = i / 3, y = i % 3; for(int k = 0; k < 4; ++k){ int nx = x + dx[k], ny = y + dy[k]; if(nx >= 0 && nx < 3 && ny >= 0 && ny < 3){ node tt = t; int nz = 3 * nx + ny; swap(tt.s[i],tt.s[nz]); tt.cantor();tt.hstar(); if(!vis[tt.v]){ vis[tt.v] = true; d[tt.v] = k; fa[tt.v] = t.v; tt.d += 1; Q.push(tt); } } } } } return false; } char str[100]; int main(void) { //freopen("input.txt","r",stdin); init(); while(~scanf("%s",str)){ memset(vis,0,sizeof(vis)); if(!sscanf(str,"%d",&st.s[0])) st.s[0] = 0; for(int i = 1; i < 9; ++i){ scanf("%s",str); if(!sscanf(str,"%d",&st.s[i])) st.s[i] = 0; } st.cantor();st.hstar(); st.d = 0; if(!Astar()) puts("unsolvable"); else{ int sz = 0; for(int v = 46233; v != st.v; v = fa[v]) path[sz++] = d[v]; for(int i = sz - 1; i >= 0; --i) putchar(dir[path[i]]); puts(""); } } return 0; }
相关文章推荐
- HDU 1043 Eight(经典八数码问题)对比POJ 1077
- POJ 1077 Eight(BFS八数码问题)
- poj 1077 Eight 八数码问题( 康拓展开+BFS状态压缩)
- poj 1077 hdu 1043 Eight 八数码问题 DBFS(双向广度优先搜索)a*算法 康拓展开
- POJ 1077 Eight(bfs八数码问题)
- hdu 1034 & poj 1077 Eight 传说中的八数码问题。真是一道神题,A*算法+康托展开
- Poj 1077 Eight 八数码问题 (搜索)
- POJ 1077 Eight 八数码问题[康托展开 + BFS]
- Poj 1077 eight(BFS+全序列Hash解八数码问题)
- POJ 1077 Eight && HDU 1043 Eight 八数码问题(A*算法)
- POJ 1077 Eight(神奇的八数码问题)
- hdu 1034 & poj 1077 Eight 传说中的八数码问题。真是一道神题,A*算法+康托展开
- POJ 1077 Eight, 八数码问题
- poj 1077 Eight A*解八数码问题
- POJ 1077 Eight 八数码问题 BFS
- poj 1077 Eight(经典八数码问题:bfs/Dbfs)
- 搜索 ( 八数码问题详解:BFS,A*,IDA* )——Eight ( POJ 1077 )
- poj 1077--Eight(八数码问题,BFS,A*,全排列的哈希)
- Poj 1077 eight(BFS+全序列Hash解八数码问题)
- POJ 1077 Eight【八数码问题】