http://acm.hdu.edu.cn/showproblem.php?pid=1043
经典八数码问题的启发式搜索
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <set> #include <map> #include <cmath> #include <queue> using namespace std; template <class T> void checkmin(T &t,T x) {if(x < t) t = x;} template <class T> void checkmax(T &t,T x) {if(x > t) t = x;} template <class T> void _checkmin(T &t,T x) {if(t==-1) t = x; if(x < t) t = x;} template <class T> void _checkmax(T &t,T x) {if(t==-1) t = x; if(x > t) t = x;} typedef pair <int,int> PII; typedef pair <double,double> PDD; typedef long long ll; #define foreach(it,v) for(__typeof((v).begin()) it = (v).begin(); it != (v).end ; it ++) struct S { char maze[3][3]; int x , y; int g , h , f; S () {} S(const S& b) { for(int i=0;i<3;i++) for(int j=0;j<3;j++) maze[i][j] = b.maze[i][j]; x=b.x; y=b.y; g=b.g; h=b.h; f=b.f; } friend bool operator < (const S& a,const S& b) { if(a.f == b.f) return a.g < b.g; return a.f > b.f; } }s; const int fac[] = {1,1,2,6,24,120,720,5040,40320}; bool vis[363000]; int pre[363000]; char op[363000]; inline int inv_hash(S b) { char str[10]; int ans = 0; for(int i=0;i<3;i++) { for(int j=0;j<3;j++) { str[i*3+j] = b.maze[i][j]; int cnt = 0; for(int k=i*3+j-1;k>=0;k--) { if(str[k] > str[i*3+j]) cnt ++; } ans += fac[i*3+j]*cnt; } } return ans; } const int pos[][2] = {{0,0},{0,1},{0,2},{1,0},{1,1},{1,2},{2,0},{2,1},{2,2}}; inline int h(S b) { int val = 0; for(int i=0;i<3;i++) { for(int j=0;j<3;j++) { if(b.maze[i][j] == 'x') continue; int c = b.maze[i][j] - '1'; val += abs(pos[c][0]-i) + abs(pos[c][1]-j); } } return val; } const int dir[4][2] = {{1,0},{0,1},{-1,0},{0,-1}}; bool bfs() { memset(vis,false,sizeof(vis)); priority_queue<S> q; q.push(s); while(!q.empty()) { S u = q.top(); q.pop(); int ihu = inv_hash(u); for(int i=0;i<4;i++) { S v = u; v.x += dir[i][0]; v.y += dir[i][1]; if(v.x<0 || v.y<0 || v.x>=3 || v.y>=3) continue; v.maze[u.x][u.y] = u.maze[v.x][v.y]; v.maze[v.x][v.y] = 'x'; v.g += 1; v.h = h(v); v.f = v.g + v.h; int ihv = inv_hash(v); if(vis[ihv]) continue; vis[ihv] = 1; pre[ihv] = ihu; if(i == 0) op[ihv] = 'd'; else if(i == 1) op[ihv] = 'r'; else if(i == 2) op[ihv] = 'u'; else if(i == 3) op[ihv] = 'l'; if(ihv == 0) return true; q.push(v); } } return false; } inline bool inv_check() { char str[10]; int cnt = 0; for(int i=0;i<3;i++) { for(int j=0;j<3;j++) { str[i*3+j] = s.maze[i][j]; if(str[i*3+j] == 'x') continue; for(int k=i*3+j-1;k>=0;k--) { if(str[k] == 'x') continue; if(str[k] > str[i*3+j]) cnt ++; } } } return !(cnt&1); } char in[100]; char stk[100]; int main() { while(gets(in)){ for(int i=0,x=0,y=0;in[i];i++){ if((in[i]<='9'&&in[i]>='0')||in[i]=='x'){ s.maze[x][y]=in[i]; if(in[i]=='x'){s.x=x;s.y=y;} y++; if(y==3) y=0,x++; } } if(!inv_check()) { puts("unsolvable"); continue; } s.g = 0; s.h = h(s); s.f = s.g + s.h; int st = inv_hash(s); if(st == 0) { puts(""); continue; } bfs(); int top = 0 , en = 0; while(en != st) { stk[top++] = op[en]; en = pre[en]; } for(int i=top-1;i>=0;i--) putchar(stk[i]); puts(""); } return 0; }