代码一:以数组充当队列,利用结构体中的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 #define AIM 1 //123456789的哈希值为1 20 21 struct node 22 { 23 int status; 24 int s[9]; 25 int loc; 26 char path; 27 int pre; //pre为上一个操作在队列中的下标,用于输出路径 28 }; 29 30 int vis[MAXN], fac[9] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320}; 31 int dir[4][2] = { -1,0, 1,0, 0,-1, 0,1 }; 32 char op[4] = {'u', 'd', 'l', 'r' }; 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 int bfs(node now) 51 { 52 ms(vis,0); 53 front = rear = 0; 54 55 now.status = cantor(now.s); 56 vis[now.status] = 1; 57 que[rear++] = now; 58 59 node tmp; 60 while(front!=rear) 61 { 62 now = que[front++]; 63 if(now.status==AIM) 64 return front-1; 65 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 tmp.path = op[i]; //保存操作 83 tmp.pre = front-1; //保存当前结点的状态的上一个状态所在的结点在数组(队列)的下标 84 que[rear++] = tmp; 85 } 86 } 87 } 88 } 89 return -1; 90 } 91 92 void Print(int i) //利用递归的特点(压栈),输出路径 93 { 94 if(i==0) return; //到了目的状态,则退出。目的状态的结点在数组(队列)中的下标为0 95 Print(que[i].pre); //访问上一步 96 putchar(que[i].path); //输出操作 97 } 98 99 int main() 100 { 101 char tmp[50]; 102 while(gets(tmp)) 103 { 104 node beg; 105 int cnt = 0; 106 for(int i = 0; tmp[i]; i++) 107 { 108 if(tmp[i]==' ') continue; 109 if(tmp[i]=='x') beg.s[cnt] = 9, beg.loc = cnt++; 110 else beg.s[cnt++] = tmp[i]-'0'; 111 112 } 113 int i = bfs(beg); 114 if(i==-1) 115 puts("unsolvable"); 116 else 117 Print(i), putchar('\n'); 118 } 119 }
代码二(推荐):把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 #define AIM 1 //123456789的哈希值为1 20 21 struct node 22 { 23 int status; 24 int s[9]; 25 int loc; 26 }; 27 28 int vis[MAXN], fac[9] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320}; 29 int dir[4][2] = { -1,0, 1,0, 0,-1, 0,1 }; 30 char op[4] = {'u', 'd', 'l', 'r' }; 31 char path[MAXN]; 32 int pre[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 queue<node>que; 49 bool bfs(node now) 50 { 51 ms(vis,0); 52 while(!que.empty()) que.pop(); 53 54 now.status = cantor(now.s); 55 pre[now.status] = -1; //开始状态的上一个状态为-1,用于输出路径时“刹车” 56 vis[now.status] = 1; 57 que.push(now); 58 59 node tmp; 60 while(!que.empty()) 61 { 62 now = que.front(); 63 que.pop(); 64 if(now.status==AIM) //找到了123456789的状态 65 return true; 66 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 pre[tmp.status] = now.status; //tmp.status的上一个状态为now.status 84 path[tmp.status] = op[i]; //保存操作 85 que.push(tmp); 86 } 87 } 88 } 89 } 90 return 0; 91 } 92 93 void Print(int status) 94 { 95 if(pre[status]==-1) return; 96 Print(pre[status]); //追溯上一个状态 97 putchar(path[status]); 98 } 99 100 int main() 101 { 102 char str[50]; 103 while(gets(str)) 104 { 105 node now; 106 int cnt = 0; 107 for(int i = 0; str[i]; i++) 108 { 109 if(str[i]==' ') continue; 110 if(str[i]=='x') now.s[cnt] = 9, now.loc = cnt++; 111 else now.s[cnt++] = str[i]-'0'; 112 } 113 if(!bfs(now)) 114 puts("unsolvable"); 115 else 116 Print(AIM), putchar('\n'); 117 } 118 }