hdu.1043.Eight (打表 || 双广 + 奇偶逆序)
Eight
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 14380 Accepted Submission(s): 4044 Special Judge
Problem 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:
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 xwhere 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
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
2 3 4 1 5 x 7 6 8
Sample Output
ullddrurdllurdruldr
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #include<ctype.h> 5 typedef long long ll ; 6 int map[5][5] ; 7 char mp[20] ; 8 int l , r , l1 , r1 ; 9 int flag ; 10 int anti ; 11 int move[][2] = {{1,0} , {-1,0} , {0,1} , {0,-1}} ; 12 const int mod = 400000 ; 13 struct node 14 { 15 int x , y , nxt ; 16 int map[3][3] ; 17 } b[mod]; 18 struct hash 19 { 20 ll w , id ; 21 int nxt ; 22 }e[mod * 2]; 23 int H[mod * 2] , E ; 24 25 void insert (ll x , int id) 26 { 27 int y = x % mod ; 28 if (y < 0) y += mod ; 29 e[++ E].w = x ; 30 e[E].id = id ; 31 e[E].nxt = H[y] ; 32 H[y] = E ; 33 } 34 35 int find (ll x) 36 { 37 int y = x % mod ; 38 if (y < 0 ) y += mod ; 39 for (int i = H[y] ; ~ i ; i = e[i].nxt ) { 40 if (e[i].w == x) 41 return e[i].id ; 42 } 43 return -1 ; 44 } 45 46 void table () 47 { 48 node ans , tmp ; 49 E = -1 ; memset (H , -1 , sizeof (H) ) ; 50 l1 = 0 , r1= 1 ; 51 b[l1].x = 2 , b[l1].y = 2 , b[l1].nxt = -1 ; 52 ll sum = 0 ; 53 for (int i = 0 ; i < 3 ; i ++) for (int j = 0 ; j < 3 ; j ++) b[l1].map[i][j] = i * 3 + j + 1 ; 54 insert (123456789 , 0 ) ; 55 while (l1 != r1) { 56 ans = b[l1] ; 57 for (int i = 0 ; i < 4 ; i ++) { 58 tmp.x = ans.x + move[i][0] ; tmp.y = ans.y + move[i][1] ; 59 if (tmp.x < 0 || tmp.y < 0 || tmp.x >= 3 || tmp.y >= 3) continue ; 60 for (int i = 0 ; i < 3 ; i ++) for (int j = 0 ; j < 3 ; j ++) tmp.map[i][j] = ans.map[i][j] ; 61 std::swap (tmp.map[ans.x][ans.y] , tmp.map[tmp.x][tmp.y]) ; 62 sum = 0 ; 63 for (int i = 0 ; i < 3 ; i ++) for (int j = 0 ; j < 3 ; j ++) sum = sum * 10 + tmp.map[i][j] ; 64 if (find (sum) != -1 ) continue ; 65 insert (sum , r1 ) ; 66 tmp.nxt = l1 ; 67 b[r1 ++] = tmp ; 68 } 69 l1 ++ ; 70 } 71 } 72 73 void solve (int u) 74 { 75 if (u == -1) return ; 76 int t = b[u].nxt ; 77 if (t != -1) { 78 int x = b[t].x - b[u].x , y = b[t].y - b[u].y ; 79 if (x == 1) printf ("d") ; 80 else if (x == -1) printf ("u") ; 81 else if (y == 1) printf ("r") ; 82 else if (y == - 1) printf ("l") ; 83 } 84 solve (t) ; 85 } 86 87 int main () 88 { 89 freopen ("a.txt" , "r" , stdin ) ; 90 table () ; 91 while (gets (mp) != NULL) { 92 int tot = 0 ; 93 for (int i = 0 ; mp[i] != '\0' ; i ++) { 94 if (mp[i] != ' ') { 95 if (isdigit (mp[i])) { 96 map[tot / 3][tot % 3] = mp[i] - '0' ; 97 } 98 else map[tot / 3][tot % 3] = 9 ; 99 tot ++ ; 100 } 101 } 102 ll sum = 0 ; 103 for (int i = 0 ; i < 3 ; i ++) for (int j = 0 ; j < 3 ; j ++) sum = sum * 10 + map[i][j] ; 104 anti = find (sum) ; 105 if (anti != -1) solve (anti) ; 106 else printf ("unsolvable") ; 107 puts ("") ; 108 } 109 return 0 ; 110 }
打表思路很简单,也是为了对抗unsolve这种情况,从123456789最终状态产生所有状态,即可.
奇偶逆序:
逆序数:也就是说,对于n个不同的元素,先规定各元素之间有一个标准次序(例如n个 不同的自然数,可规定从小到大为标准次序),于是在这n个元素的任一排列中,当某两个元素的先后次序与标准次序不同时,就说有1个逆序。一个排列中所有逆序总数叫做这个排列的逆序数。
结论:(是除去移动元素,(这里是9))
对源状态A与目标状态B进行规范化,使得两矩阵的元素0的位置相同;记为新的源状态A'与目标状态B';
若A'与B'的逆序对的奇偶性相同(即A'与B1的逆序对的奇偶性相同),则A'必定可能转化为B',即A可以转化到B;
若A'与B'的逆序对的奇偶性不同(即A'与B2的逆序对的奇偶性相同),则A'必定不可能转化为B',即A不可以转化到B;
也就是为了对抗unsolve.
然后用双广就OK了.