Description
The 15-puzzle has been around for over 100 years; even if you don't know it by that name, you've seen it. It is constructed with 15 sliding tiles, each with a number from 1 to 15 on it, and all packed into a 4 by 4 frame with one tile missing. Let's call the missing tile 'x'; the object of the puzzle is to arrange the tiles so that they are ordered as:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 x
where the only legal operation is to exchange 'x' with one of the tiles with which it shares an edge. As an example, the following sequence of moves solves a slightly scrambled puzzle:
1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4
5 6 7 8 5 6 7 8 5 6 7 8 5 6 7 8
9 x 10 12 9 10 x 12 9 10 11 12 9 10 11 12
13 14 11 15 13 14 11 15 13 14 x 15 13 14 15 x
r-> d-> r->
The letters in the previous row indicate which neighbor of the 'x' tile is swapped with the 'x' tile at each step; legal values are 'r','l','u' and 'd', for right, left, up, and down, respectively.
Not all puzzles can be solved; in 1870, a man named Sam Loyd was famous for distributing an unsolvable version of the puzzle, and
frustrating many people. In fact, all you have to do to make a regular puzzle into an unsolvable one is to swap two tiles (not counting the missing 'x' tile, of course).
In this problem, you will write a program for solving the less well-known 8-puzzle, composed of tiles on a three by three
arrangement.
Input
You will receive, several descriptions of configuration of the 8 puzzle. One description is just a list of the tiles in their initial positions, with the rows listed from top to bottom, and the tiles listed from left to right within a row, where the tiles are represented by numbers 1 to 8, plus 'x'. For example, this puzzle
1 2 3
x 4 6
7 5 8
is described by this list:
1 2 3 x 4 6 7 5 8
Output
You will print to standard output either the word ``unsolvable'', if the puzzle has no solution, or a string consisting entirely of the letters 'r', 'l', 'u' and 'd' that describes a series of moves that produce a solution. The string should include no spaces and start at the beginning of the line. Do not print a blank line between cases.
Sample Input
Sample Input
1 #include <iostream> 2 #include <cstring> 3 4 using namespace std; 5 6 const int maxn = 1000003; 7 typedef int State[9]; 8 State st[maxn]; 9 int goal[] = {1, 2, 3, 4, 5, 6, 7, 8, 0}; 10 int dx[] = {-1, 1, 0, 0}; 11 int dy[] = { 0, 0, -1, 1}; 12 int head[maxn], nxt[maxn], fa[maxn]; 13 char dir[maxn]; 14 15 int Hash(State s) //哈希函数 16 { 17 int ret = 0, i; 18 for(i = 0; i < 9; i++) ret = ret * 10 + s[i]; 19 return ret % maxn; 20 } 21 22 bool try_to_insert(int rear) //插入哈希表 23 { 24 int h = Hash(st[rear]); 25 for(int e = head[h]; e != -1; e = nxt[e]) 26 { 27 if(memcmp(st[e], st[rear], sizeof(st[e])) == 0) return 0; 28 } 29 nxt[rear] = head[h]; 30 head[h] = rear; 31 return 1; 32 } 33 34 int bfs() //遍历 35 { 36 int frt = 1, rear = 2, i, z; 37 while(frt < rear) 38 { 39 State& s = st[frt]; 40 if(memcmp(s, goal, sizeof(s)) == 0) return frt; 41 for(z = 0; s[z] != 0; z++); 42 int x = z / 3; 43 int y = z % 3; 44 for(i = 0; i < 4; i++) 45 { 46 int newx = x + dx[i]; 47 int newy = y + dy[i]; 48 int newz = 3 * newx + newy; 49 if(newx >= 0 && newx < 3 && newy >= 0 && newy < 3) 50 { 51 State& news = st[rear]; 52 memcpy(news, s, sizeof(s)); 53 news[z] = s[newz]; 54 news[newz] = 0; 55 if(try_to_insert(rear)) //注意这里的路径输出的方式 56 { 57 fa[rear] = frt; 58 switch(i) 59 { 60 case 0: dir[rear] = 'u'; break; 61 case 1: dir[rear] = 'd'; break; 62 case 2: dir[rear] = 'l'; break; 63 case 3: dir[rear] = 'r'; break; 64 default: break; 65 } 66 rear++; 67 } 68 } 69 } 70 frt++; 71 } 72 return 0; 73 } 74 75 void print(int i) //输出 76 { 77 if(fa[i] == -1) return; 78 print(fa[i]); 79 cout<<dir[i]; 80 } 81 82 int main() 83 { 84 char c[10]; 85 int i, ret; 86 while(cin>>c[0]>>c[1]>>c[2]>>c[3]>>c[4]>>c[5]>>c[6]>>c[7]>>c[8]) 87 { 88 for(i = 0; i < 9; i++) st[1][i] = c[i] == 'x' ? 0 : (int)(c[i]-'0'); 89 memset(head, -1, sizeof(head)); 90 fa[1] = -1; 91 ret = bfs(); 92 if(ret) 93 { 94 print(ret); 95 } 96 else cout<<"unsolvable"; 97 cout<<endl; 98 } 99 return 0; 100 }
HDU : 这道题时多组输入,所以不能向上面一样在线写,而是要从最终状态开始倒着把所有状态搜索一遍,之后只需要输入初始状态打表判断输出路径即可;
学习到的知识有两个:bfs()路径查找类 + 康拓展开,路径的输出:
1 /************************************************************************* 2 > File Name: search.cpp 3 > Author : PrayG 4 > Mail: 996930051@qq,com 5 > Created Time: 2016年07月20日 星期三 10时56分09秒 6 ************************************************************************/ 7 8 #include<iostream> 9 #include<cstdio> 10 #include<cstring> 11 #include<string> 12 #include<queue> 13 #include<algorithm> 14 #include<map> 15 #include<stack> 16 #include<set> 17 #include<cmath> 18 using namespace std; 19 const int maxn = 362900; 20 int fac[] = {1,1,2,6,24,120,720,5040,40320,362880}; 21 int dx[] = {1,0,-1,0},dy[] = {0,1,0,-1};//drul 22 char ind[5] = "uldr";//与上面相反 23 string path[maxn];//记录路径 24 bool vis[maxn]; 25 int aim = 46233;//123456780 的康拓展开 26 27 struct node 28 { 29 int s[9]; //记录状态 30 int sit0; //0 的位置 31 int val; //康拓展开的值 32 string path; // 路径 33 }; 34 35 int cant(int s[]) //康拓展开 36 { 37 int code = 0; 38 for(int i = 0; i < 9; i++) 39 { 40 int cnt = 0; 41 for(int j= i+1 ; j < 9; j++) 42 { 43 if(s[i] > s[j]) 44 { 45 cnt++; 46 } 47 } 48 code += fac[8-i] * cnt; 49 } 50 return code; 51 } 52 53 void bfs() 54 { 55 memset(vis,false,sizeof(vis)); 56 queue<node> que; 57 node cnt1,cnt2; 58 for(int i = 0 ; i < 8;i++) 59 cnt1.s[i] = i+1; 60 cnt1.s[8] = 0; 61 cnt1.sit0 = 8; 62 //printf("aim = %d ",aim); 63 cnt1.val = aim; 64 cnt1.path = ""; 65 path[aim] = ""; 66 que.push(cnt1); 67 while(!que.empty()) 68 { 69 cnt1 = que.front(); 70 que.pop(); 71 int x = cnt1.sit0 / 3; 72 int y = cnt1.sit0 % 3; 73 for(int i = 0; i < 4; i++) 74 { 75 int nx = x + dx[i]; 76 int ny = y + dy[i]; 77 int nz = nx * 3 + ny; 78 if(nx < 0 || nx >2 || ny <0 || ny >2) 79 continue; 80 cnt2 = cnt1; 81 cnt2.s[cnt1.sit0] = cnt2.s[nz]; 82 cnt2.s[nz] = 0; 83 cnt2.sit0 = nz; 84 cnt2.val = cant(cnt2.s); 85 if(!vis[cnt2.val]) 86 { 87 vis[cnt2.val] = true; 88 cnt2.path = ind[i] + cnt1.path; 89 que.push(cnt2); 90 path[cnt2.val] = cnt2.path; 91 } 92 } 93 94 } 95 } 96 97 int main() 98 { 99 bfs(); 100 char t; 101 while(cin >> t) 102 { 103 node st; 104 if(t == 'x'){ 105 st.s[0] = 0; 106 st.sit0 = 0; 107 } 108 else 109 st.s[0] = t - '0'; 110 for(int i = 1; i< 9; i++) 111 { 112 cin >> t; 113 if(t == 'x') 114 { 115 st.s[i] = 0; 116 st.sit0 = i; 117 } 118 else 119 st.s[i] = t -'0'; 120 } 121 st.val = cant(st.s); 122 if(vis[st.val]) 123 { 124 cout << path[st.val] << endl; 125 } 126 else 127 cout << "unsolvable" << endl; 128 } 129 return 0; 130 }