bnuoj 1071 拼图++

问题描述

拼图玩具已经有约235年的历史了。早在1760年,法英两国几乎同时出现这种既流行又有益的娱乐方式。把一张图片粘在硬纸板上,然后把它剪成不规则小碎片。最初这些图片都是有教育意义的,要么附有适于年轻人阅读的短文,要么向新兴资产阶级传授历史或地理知识。
1762年,在法国路易十五统治时期,一个名叫迪马的推销商开始推销地图拼图,取得小小成功。这种地图拼图要求把碎片重新排列,是一种文雅的娱乐活动。同年,在伦敦,一位名叫约翰•斯皮尔斯伯里的印刷工也想到了相似的主意,发明了经久不衰的拼图玩具。他极其巧妙地把一幅英国地图粘到一张很薄的餐桌背面,然后沿着各郡县的边缘精确地把地图切割成小块。这一想法能带来巨额财富,但可怜的斯皮尔斯伯里并没有得到这笔钱,他只活了29岁,没能看到拼图玩具的巨大成功。他成功的真正意义在于,他为自己的发明打开了两个重要的市场:渴求知识的新兴中产阶级消费者,以及他所处时代严厉苛刻的英国学校。
现在很多手机、电子词典上都有这款游戏,一个很普遍的版本就是在一个3×3的方格中有8块1×1的图片块以及一个空格,通过移动这些被打乱的图块就能得到原图。
但是,这种类型的拼图却存在无解的情形,并且将近有一半的状态无解,这是YC不愿意看到的,他希望构造一种一定有解的拼图游戏。经过了N天的思考以后,他终于在原拼图游戏的基础上综合了一下魔方的玩法,总结出了一种新的玩法(也可能是老玩法,只是YC知识不够渊博没有发现……),玩法如下。
给出一个3×3的方格,其中有9块1×1的图片块,没有空格,每一次,玩家都能选取其中任意一个2×2的方格进行旋转,顺时针或者逆时针均可,但是每一次旋转只能旋转一格。YC把这个游戏告诉了WSY大牛,WSY大牛对这比较感兴趣,在那转啊转啊,可是却把自己弄晕了……(Orz……)于是,WSY大牛决定发挥CODER本色,编写一个程序,告诉他对于给定的任意一种起始图和目标图,最少需要多少次旋转。然后,他就可以向YC炫耀说他在多少步之内就解决了YC给他的问题。(YC不会问WSY大牛他是如何解出来的,因为YC对WSY大牛是膜拜状态……)

Input

第一行:一个整数K(K≤50),代表数据组数。
对于每一组数据:
第一行:9个整数,表示初始图形。
第二行:9个整数,表示目标图形。
每一组数据之前和之后都有一个空行。
9个整数范围都在1~9且不重复,出现顺序为3×3方格从最左上的方格开始,依次从左到右的、从上到下。

 

Output

对于每组数据,输出一行答案,即所需的最少步数,格式参照样例。

 

Sample Input

2

1 2 3 4 5 6 7 8 9
4 1 3 5 2 6 7 8 9

1 2 3 4 9 8 7 6 5
1 2 3 4 5 6 7 8 9

 

Sample Output

Number Of Move(s) Needed: 1
Number Of Move(s) Needed: 2

 

Hint

样例说明:
第一组:左上角顺时针旋转一次即可。
1 2 3       4 1 3
4 5 6  -->  5 2 6
7 8 9       7 8 9
第二组:右下角顺时针或者逆时针旋转两次均可。
顺:
1 2 3       1 2 3       1 2 3
4 9 8  -->  4 6 9  -->  4 5 6
7 6 5       7 5 8       7 8 9
逆:
1 2 3       1 2 3       1 2 3
4 9 8  -->  4 8 5  -->  4 5 6
7 6 5       7 9 6       7 8 9

 

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <queue>
  5 using namespace std;
  6 int startS,endS;
  7 const int MAXN=400000;
  8 
  9 struct node
 10 {
 11     int s[3][3];
 12     int staus;
 13 };
 14 int vis[MAXN];//标记
 15 int fac[]={1,1,2,6,24,120,720,5040,40320,362880};
 16 
 17 int cantor(int s[3][3])
 18 {
 19     int ans[10];
 20     int ll=0;
 21     for(int i=0;i<3;i++)
 22     {
 23         for(int j=0;j<3;j++)
 24         {
 25             ans[ll++]=s[i][j];
 26         }
 27     }
 28     int sum=0;
 29     for(int i=0;i<9;i++)
 30     {
 31         int num=0;
 32         for(int j=i+1;j<9;j++)
 33           if(ans[j]<ans[i])num++;
 34         sum+=(num*fac[9-i-1]);
 35     }
 36     return sum+1;
 37 }
 38 
 39 void cpy(int a[][3],int b[][3])
 40 {
 41     for(int i=0;i<3;i++)
 42     {
 43         for(int j=0;j<3;j++)
 44         {
 45             a[i][j]=b[i][j];
 46         }
 47     }
 48 }
 49 
 50 void bfs()
 51 {
 52     int K[3][3]={{1,2,3},{4,5,6},{7,8,9}};
 53     memset(vis,-1,sizeof(vis));
 54     node p;
 55     cpy(p.s,K);
 56     p.staus=cantor(K);
 57     queue<node>q;
 58     vis[p.staus]=0;
 59     while(!q.empty())
 60     q.pop();
 61     q.push(p);
 62     while(!q.empty())
 63     {
 64         p=q.front();
 65         q.pop();
 66         for(int i=0;i<2;i++)
 67         {
 68             for(int j=0;j<2;j++)
 69             {
 70                 node temp1,temp2;
 71                 cpy(temp1.s,p.s);
 72                 int tmp;
 73                 tmp=temp1.s[i][j],temp1.s[i][j]=temp1.s[i][j+1],temp1.s[i][j+1]=temp1.s[i+1][j+1],temp1.s[i+1][j+1]=temp1.s[i+1][j],temp1.s[i+1][j]=tmp;
 74                 temp1.staus=cantor(temp1.s);
 75                 if(vis[temp1.staus]==-1)
 76                 {
 77                     vis[temp1.staus]=vis[p.staus]+1;
 78                     q.push(temp1);
 79                 }
 80                 cpy(temp2.s,p.s);
 81                 tmp=temp2.s[i][j],temp2.s[i][j]=temp2.s[i+1][j],temp2.s[i+1][j]=temp2.s[i+1][j+1],temp2.s[i+1][j+1]=temp2.s[i][j+1],temp2.s[i][j+1]=tmp;
 82                 temp2.staus=cantor(temp2.s);
 83                 if(vis[temp2.staus]==-1)
 84                 {
 85                     vis[temp2.staus]=vis[p.staus]+1;
 86                     q.push(temp2);
 87                 }
 88             }
 89         }
 90     }
 91 }
 92 int main()
 93 {
 94     int t;
 95     int S[10];
 96     int TT[3][3];
 97     scanf("%d",&t);
 98     bfs();
 99     while(t--)
100     {
101         for(int i=1;i<=9;i++)
102         {
103             int a;
104             scanf("%d",&a);
105             S[a]=i;
106         }
107         for(int i=0;i<3;i++)
108         {
109             for(int j=0;j<3;j++)
110             {
111                 int a;
112                 scanf("%d",&a);
113                 TT[i][j]=S[a];
114             }
115         }
116         printf("Number Of Move(s) Needed: %d\n",vis[cantor(TT)]);
117     }
118     return 0;
119 }
View Code

此题比较裸的康拓展开,先BFS预处理出所有可能。

然后分别输入起始状态和最终状态。

对应预处理时的最初状态,相应的的根据起始状态将最终状态进行转化。

然后直接输出结果即可。。

posted @ 2013-09-21 20:31  欧阳生朵  阅读(304)  评论(0编辑  收藏  举报