24 Puzzle
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65768/65768 K (Java/Others)
Total Submission(s): 1466 Accepted Submission(s): 433
Problem Description
Daniel likes to play a special board game, called 24 puzzle. 24 puzzle is such a game that there are tiles with the number 1 to 23 in a play board like the follow picture:
The ‘#’ denotes the positions that the tiles may be placed on. There are 24 possible positions in total, so one of them is not occupied by the tile. We can denote the empty position by zero.
Daniel could move the tiles to the empty position if the tile is on the top, bottom, left or right of the empty position. In this way Daniel can reorder the tiles on the board.
Usually he plays with this game by setting up a target states initially, and then trying to do a series of moves to achieve the target. Soon he finds that not all target states could be achieved.
He asks for your help, to determine whether he has set up an impossible target or not.
Input
The first line of input contains an integer denoting the number of test cases.
For each test case, the first line contains 24 integers denoting the initial states of the game board. The numbers are the describing the tiles from top to bottom, left to right. And the empty position is indicated by zero. You can assume that the number of each tile are different, and there must be exactly one empty position. The second line of test case also contains 24 integers denoting the target states.
Output
For each test case, if the target is impossible to achieve, output ‘Y’ in a single line, otherwise, output ‘N’.
Sample Input
2
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
3 1 2 0 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
3 0 2 1 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
Sample Output
N
Y
题目意思:
给出上面一个棋盘,#为格子,0---23数字放在格子上且不重复,0表示这个格子为空,每个数字可以走到上、下、左、右四个临近且为空的格子处。给出起始状态和目标状态,问是否能从起始状态走到目标状态,若能输出N,否则输出Y。
思路:
这个就是8数码问题变化了一下。先说8数码问题吧。
8数码问题就是3*3的木板,由0--8数字填充,0表示空,问是否能从起始状态达到目标状态。
交换位置的时候只能左右交换和上下交换。若把木板数字从左到右从上到下的数字(不包括0)放在数组中,那么左右交换的时候数组逆序数奇偶性不变,若上下交换的时候,逆序数变化为+2、0、-2,奇偶性不变。那么若起始状态的奇偶性与目标状态的奇偶性不同一定没法达到,反之一定可以达到(大家都玩过这种游戏吧,就是3*3的方格,7个方格里一个不同的图片,随着图片向空白的地方移动,达到咱们想要的组成图片,仔细一点会发现这种游戏没有达不到的结果,一定会达到的,只是用的步数多或少的问题)。
那么这道题中,上下左右分别有两个死角,一旦数字填充到这个死角后那么死角的数字不可能发生变化,那么咱们先把死角填充完毕,然后比较起始状态和目标状态死角的数字,若不同,那么一定达不到。反之就看中间4*4的方格是否可以达到,而4*4方格不就是n数码问题么。
同理,左右交换不改变逆序数,上下交换时候逆序数变化为+1、-1、+3、-3,奇偶性一定会变化,那么算出初始逆序数和目标逆序数,然后算出空白位置行差,看一下初始逆序数+行差的奇偶性和目标逆序数奇偶性是否相同就行了。
我的代码写的有点菜,看过上面思路基本上就能写出来了
代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <queue> 6 #include <vector> 7 #include <map> 8 #include <set> 9 using namespace std; 10 11 int b[105]; 12 __int64 num; 13 void bing(int st,int mid,int end,int a[]) 14 { 15 int i, j, k; 16 for(i=st;i<=end;i++) 17 b[i]=a[i]; 18 i=st;j=mid+1;k=st; 19 while(i<=mid&&j<=end) 20 { 21 if(b[i]<=b[j]) 22 { 23 a[k++]=b[i++]; 24 } 25 else{ 26 a[k++]=b[j++]; 27 num+=(mid-i+1); 28 } 29 } 30 while(i<=mid) 31 a[k++]=b[i++]; 32 while(j<=end) 33 a[k++]=b[j++]; 34 } 35 void msort(int st,int end,int a[]) 36 { 37 if(st<end) 38 { 39 int t=(st+end)/2; 40 msort(st,t,a); 41 msort(t+1,end,a); 42 bing(st,t,end,a); 43 } 44 } 45 main() 46 { 47 int n, i, j, a, k, k1, t, f; 48 int a1[105], a2[105], c1[105], c2[105], d1[105], d2[105]; 49 cin>>t; 50 int x, y, z1, z2; 51 while(t--){ 52 k=0; 53 k1=1; 54 for(i=1;i<=24;i++){ 55 scanf("%d",&a); 56 if(i==1||i==2||i==3||i==8||i==17||i==22||i==23||i==24){ 57 a1[k++]=a; 58 } 59 else{ 60 c1[k1++]=a; 61 } 62 } 63 64 k=0;k1=1; 65 for(i=1;i<=24;i++){ 66 scanf("%d",&a); 67 if(i==1||i==2||i==3||i==8||i==17||i==22||i==23||i==24){ 68 a2[k++]=a; 69 } 70 else{ 71 c2[k1++]=a; 72 } 73 } 74 75 for(i=0;i<8;i++){ 76 if(a1[i]==0){ 77 if(i==0||i==2) swap(a1[i],c1[1]); 78 else if(i==1||i==3) swap(a1[i],c1[4]); 79 else if(i==4||i==6) swap(a1[i],c1[13]); 80 else if(i==5||i==7) swap(a1[i],c1[16]); 81 } 82 } 83 for(i=0;i<8;i++){ 84 if(a2[i]==0){ 85 if(i==0||i==2) swap(a2[i],c2[1]); 86 else if(i==1||i==3) swap(a2[i],c2[4]); 87 else if(i==4||i==6) swap(a2[i],c2[13]); 88 else if(i==5||i==7) swap(a2[i],c2[16]); 89 } 90 } 91 k=1; 92 for(i=1;i<=16;i++) { 93 if(!c1[i]) x=(i-1)/4+1; 94 else d1[k++]=c1[i]; 95 } 96 k=1; 97 for(i=1;i<=16;i++) { 98 if(!c2[i]) y=(i-1)/4+1; 99 else d2[k++]=c2[i]; 100 } 101 /* for(i=0;i<8;i++) printf("%d ",a1[i]); 102 cout<<endl; 103 for(i=0;i<8;i++) printf("%d ",a2[i]); 104 cout<<endl; 105 for(i=1;i<=16;i++) printf("%d ",c1[i]); 106 cout<<endl; 107 for(i=1;i<=16;i++) printf("%d ",c2[i]); 108 cout<<endl;*/ 109 f=1; 110 for(i=0;i<8;i++){ 111 if(a1[i]!=a2[i]){ 112 f=0;break; 113 } 114 } 115 if(!f){ 116 printf("Y\n");continue; 117 } 118 num=0; 119 msort(1,15,d1); 120 z1=num; 121 num=0; 122 msort(1,15,d2); 123 z2=num; 124 125 if(((z1+z2)%2)==((abs(y-x))%2)){ 126 printf("N\n"); 127 } 128 else printf("Y\n"); 129 } 130 }