主页面:http://www.cnblogs.com/DOLFAMINGO/p/7538588.html
代码一:以数组充当队列,利用结构体中的pre追溯上一个状态在数组(队列)中的下标:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <vector> 7 #include <queue> 8 #include <stack> 9 #include <map> 10 #include <string> 11 #include <set> 12 #define ms(a,b) memset((a),(b),sizeof((a))) 13 using namespace std; 14 typedef long long LL; 15 const int INF = 2e9; 16 const LL LNF = 9e18; 17 const int MOD = 1e9+7; 18 const int MAXN = 1e6+10; 19 20 struct node 21 { 22 int status; 23 int s[9]; 24 int loc; 25 char op; 26 int pre; //pre为上一个操作在队列中的下标,用于输出路径 27 }; 28 29 int vis[MAXN], fac[9] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320}; 30 int dir[4][2] = { 0,1,0,-1, 1,0, -1,0 }; 31 char op[4] = {'l', 'r', 'u', 'd' }; //由于反向操作,则方向应该反过来 32 int id[MAXN]; 33 34 int cantor(int s[]) //获得哈希函数值 35 { 36 int sum = 0; 37 for(int i = 0; i<9; i++) 38 { 39 int num = 0; 40 for(int j = i+1; j<9; j++) 41 if(s[j]<s[i]) 42 num++; 43 sum += num*fac[8-i]; 44 } 45 return sum+1; 46 } 47 48 node que[MAXN]; 49 int front, rear; 50 void bfs() 51 { 52 ms(vis, 0); 53 front = rear = 0; 54 55 node now, tmp; 56 for(int i = 0; i<9; i++) //初始状态为123456789 57 now.s[i] = i+1; 58 now.loc = 8; 59 now.status = cantor(now.s); 60 vis[now.status] = 1; 61 id[now.status] = rear; //初始状态在队列中的下标 62 que[rear++] = now; 63 64 while(front!=rear) 65 { 66 now = que[front++]; 67 int x = now.loc/3; 68 int y = now.loc%3; 69 for(int i = 0; i<4; i++) 70 { 71 int xx = x + dir[i][0]; 72 int yy = y + dir[i][1]; 73 if(xx>=0 && xx<=2 && yy>=0 && yy<=2) 74 { 75 tmp = now; 76 tmp.s[x*3+y] = tmp.s[xx*3+yy]; 77 tmp.s[xx*3+yy] = 9; 78 tmp.status = cantor(tmp.s); 79 if(!vis[tmp.status]) 80 { 81 vis[tmp.status] = 1; 82 tmp.loc = xx*3+yy; 83 tmp.op = op[i]; 84 tmp.pre = front-1; 85 id[tmp.status] = rear; 86 que[rear++] = tmp; 87 } 88 } 89 } 90 } 91 } 92 93 void Print(int i) 94 { 95 if(i==0) return; //队列下标为0的时候为初始状态, 应返回 96 putchar(que[i].op); //输出操作 97 Print(que[i].pre); //访问BFS的上一步,但因为是反向BFS,所以对于答案来说是下一步,应放在putchar后面 98 } 99 100 int main() 101 { 102 bfs();//反向bfs,预处理所有情况。然后在访问的时候直接输出路径 103 char str[50]; 104 while(gets(str)) 105 { 106 node aim; 107 int cnt = 0; 108 for(int i = 0; str[i]; i++) 109 { 110 if(str[i]==' ') continue; 111 if(str[i]=='x') aim.s[cnt] = 9, aim.loc = cnt++; 112 else aim.s[cnt++] = str[i]-'0'; 113 } 114 aim.status = cantor(aim.s); 115 if(!vis[aim.status]) 116 puts("unsolvable"); 117 else 118 Print(id[aim.status]), putchar(' '); 119 } 120 }
代码二(推荐):把pre和path放在结构体外,利用当前状态status追溯上一个状态status:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <vector> 7 #include <queue> 8 #include <stack> 9 #include <map> 10 #include <string> 11 #include <set> 12 #define ms(a,b) memset((a),(b),sizeof((a))) 13 using namespace std; 14 typedef long long LL; 15 const int INF = 2e9; 16 const LL LNF = 9e18; 17 const int MOD = 1e9+7; 18 const int MAXN = 1e6+10; 19 20 struct node 21 { 22 int status; 23 int s[9]; 24 int loc; 25 }; 26 27 int vis[MAXN], fac[9] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320}; 28 int dir[4][2] = { 0,1,0,-1, 1,0, -1,0 }; 29 char op[4] = {'l', 'r', 'u', 'd' }; //由于反向操作,则方向应该反过来 30 char path[MAXN]; 31 int pre[MAXN]; 32 33 int cantor(int s[]) //获得哈希函数值 34 { 35 int sum = 0; 36 for(int i = 0; i<9; i++) 37 { 38 int num = 0; 39 for(int j = i+1; j<9; j++) 40 if(s[j]<s[i]) 41 num++; 42 sum += num*fac[8-i]; 43 } 44 return sum+1; 45 } 46 47 queue<node>que; 48 void bfs() 49 { 50 ms(vis, 0); 51 while(!que.empty()) que.pop(); 52 53 node now, tmp; 54 for(int i = 0; i<9; i++) //初始状态为123456789 55 now.s[i] = i+1; 56 now.loc = 8; 57 now.status = cantor(now.s); 58 vis[now.status] = 1; 59 pre[now.status] = -1; 60 que.push(now); 61 62 while(!que.empty()) 63 { 64 now = que.front(); 65 que.pop(); 66 int x = now.loc/3; 67 int y = now.loc%3; 68 for(int i = 0; i<4; i++) 69 { 70 int xx = x + dir[i][0]; 71 int yy = y + dir[i][1]; 72 if(xx>=0 && xx<=2 && yy>=0 && yy<=2) 73 { 74 tmp = now; 75 tmp.s[x*3+y] = tmp.s[xx*3+yy]; 76 tmp.s[xx*3+yy] = 9; 77 tmp.status = cantor(tmp.s); 78 if(!vis[tmp.status]) 79 { 80 vis[tmp.status] = 1; 81 tmp.loc = xx*3+yy; 82 path[tmp.status] = op[i]; 83 pre[tmp.status] = now.status; 84 que.push(tmp); 85 } 86 } 87 } 88 } 89 } 90 91 void Print(int status) 92 { 93 if(pre[status]==-1) return; 94 putchar(path[status]); 95 Print(pre[status]); 96 } 97 98 int main() 99 { 100 bfs();//反向bfs,预处理所有情况。然后在访问的时候直接输出路径 101 char str[50]; 102 while(gets(str)) 103 { 104 node aim; 105 int cnt = 0; 106 for(int i = 0; str[i]; i++) 107 { 108 if(str[i]==' ') continue; 109 if(str[i]=='x') aim.s[cnt] = 9, aim.loc = cnt++; 110 else aim.s[cnt++] = str[i]-'0'; 111 } 112 aim.status = cantor(aim.s); 113 if(!vis[aim.status]) 114 puts("unsolvable"); 115 else 116 Print(aim.status), putchar(' '); 117 } 118 }