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: 
 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
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] != '' ; 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 }
View Code

打表思路很简单,也是为了对抗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了.

原文地址:https://www.cnblogs.com/get-an-AC-everyday/p/4468700.html