HDU 4021 八数码问题

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 }
时间: 2024-10-23 04:19:42

HDU 4021 八数码问题的相关文章

HDU 1043 八数码(A*搜索)

在学习八数码A*搜索问题的时候需要知道以下几个点: Hash:利用康托展开进行hash 康托展开主要就是根据一个序列求这个序列是第几大的序列. A*搜索:这里的启发函数就用两点之间的曼哈顿距离进行计算就可以. 减枝:在八数码里,任意交换一个空行和一个位置的数字,这个八数码的逆序数是不变的,这样就可以根据目前状态判断是否可达终点状态了. 第一次做这个题用的map进行哈希,结果果断超时,之后又写了LRJ书上的hash方法也超时了,最后只能用康托展开了 详细请参考:[八数码的八重境界] http://

hdu 4021 n数码

好题,6666 转自:http://www.cnblogs.com/kuangbin/archive/2012/08/23/2652410.html 题意:给出一个board,上面有24个位置,其中23个位置上放置了标有数字1~23的方块,一个为空位(用数字0表示),现在可以把空位与它旁边的方块交换,给出board的起始状态,问是否可以达到指定的状态. 思路:看起来很像著名的“八数码”问题,首先,针对八个特殊位置(死角),如果这里有空位就把它和相邻的位置交换,这样之后如果两个状态的对应死角上的数

HDU 1043 八数码(八境界)

8境界:http://www.cnblogs.com/goodness/archive/2010/05/04/1727141.html 境界一. 暴力广搜+STL (HDU 内存超限,POJ 时间超限) map存路径,set判重,string存状态,毫无疑问,炸了. #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<vector> #inclu

HDU 1043 Eight八数码解题思路(bfs+hash 打表 IDA* 等)

题目链接 https://vjudge.net/problem/HDU-1043 经典的八数码问题,学过算法的老哥都会拿它练搜索 题意: 给出每行一组的数据,每组数据代表3*3的八数码表,要求程序复原为初始状态 思路: 参加网站比赛时拿到此题目,因为之前写过八数码问题,心中暗喜,于是写出一套暴力bfs+hash,结果TLE呵呵 思路一:bfs+hash(TLE) 1 #include <cstdio> 2 #include <cstring> 3 #include <queu

HDU 3567 Eight II(八数码 II)

p.MsoNormal { margin: 0pt; margin-bottom: .0001pt; text-align: justify; font-family: Calibri; font-size: 10.5000pt } h1 { margin-top: 5.0000pt; margin-bottom: 5.0000pt; text-align: center; font-family: 宋体; color: rgb(26,92,200); font-weight: bold; fo

HDU 1043 POJ 1077 八数码问题

以下内容转载自:http://www.cnblogs.com/goodness/archive/2010/05/04/1727141.html 八数码的八境界 研究经典问题,空说不好,我们拿出一个实际的题目来演绎.八数码问题在北大在线测评系统中有一个对应的题,题目描述如下: Eight Time Limit: 1000MS    Memory Limit: 65536K  Special Judge Description The 15-puzzle has been aroundfor ove

HDU 1043 Eight(八数码)

p.MsoNormal { margin: 0pt; margin-bottom: .0001pt; text-align: justify; font-family: Calibri; font-size: 10.5000pt } h1 { margin-top: 5.0000pt; margin-bottom: 5.0000pt; text-align: center; font-family: 宋体; color: rgb(26,92,200); font-weight: bold; fo

Hdu 1043 Eight (八数码问题)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1043 题目描述: 3*3的格子,填有1到8,8个数字,还有一个x,x可以上下左右移动,问最终能否移动到12345678x的状态? hint:每一个3*3的格子从上到右,从左到右,一行一行读. 解题思路: 比较简单的八数码问题,大一暑假老师讲过,一直手懒脑懒并没有亲自尝试过.因为是多实例,先从12345678x的状态bfs出来所有可以到达的状态,并且记录下来路径.八数码最重要的就是保存状态,如果这个

hdu 1034 Eight 传说中的八数码问题。真是一道神题,A*算法+康托展开

Eight Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 13506    Accepted Submission(s): 3855 Special Judge Problem Description The 15-puzzle has been around for over 100 years; even if you don'