HDU 4531 bfs/康拓展开

题目链接http://acm.hdu.edu.cn/showproblem.php?pid=4531

吉哥系列故事——乾坤大挪移

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 555    Accepted Submission(s): 178


Problem Description
  只有进入本次马拉松复赛,你才有机会知道一个秘密:吉哥的真名叫基哥,江湖人称“叽叽哥”。

  叽叽哥除了编程,还一直有个武侠梦,他最喜欢的人物是金庸小说《倚天屠龙记》中的张无忌,不仅有美人环绕,而且有一身的好武功,尤其是那神秘的乾坤大挪移,让他梦寐以求:
  
  “乾坤大挪移乃在颠倒一刚一柔、一阴一阳的乾坤二气,随意而行,不用心而无不心用,所谓至我逍遥游,以纯阳之身,和纯阴之体,合练双修,不动身,只用意,意动身守......”
  
  但是,梦毕竟只是梦,平时在编程的空闲时间,叽叽哥也最多只能上网玩一下名为“乾坤大挪移”的游戏聊以自慰而已。
  这个“乾坤大挪移”游戏是在3*3的方格中进行。
  游戏的目标是通过移动,让相同颜色的块形成一个连通块(相邻是指两个块有边相邻,角相邻不算)。
  移动规则如下:选择一行(列),向左右(上下)移动一格,方格从一边划出,则从对应的另外一边划入,像履带一样。
  如选择第一行向右边移动,最右边的那格会移动到最左边。
  游戏中还有一些方格被固定住,这些方格没办法移动(如下图的第三行第二列)。
  下图是游戏的一个演示(即Case 1):



  假设现在告诉你初始状态,请问你最少需要几步才能达到目标?
 

 

Input
第一行一个整数T代表接下去有T组数据;
每组数据由3*3的模块组成,每个模块表示的小正方形是由上下左右四个小三角形组成;
每个模块有5个字符,前四个字符分别表示组成正方形的上下左右四个小三角形的颜色,第五个字符表示该格子能否移动(0表示能移动,1表示不能移动).

[Technical Specification]
0<T<=100
代表颜色的字符一定是RGBO的其中一个
代表能否移动移动的字符一定是0或者1
 

 

Output
首先输出case数,接着输出最小的移动步数使得游戏达到目标状态(见sample);
数据保证有解。
 

 

Sample Input
2 GGGG0 GGGG0 GGGG0 OGOO0 GGGG0 OGOO0 OOOO0 OGGG1 OOOO0 RRRR0 OOOO0 OOOO0 OOOO0 OOOO0 OOOO0 OOOO0 OOOO0 RRRR0
 

 

Sample Output
Case #1: 5 Case #2: 2
 

 

Source
 看到题目,确实感觉有点麻烦,很考验代码能力,代码能力差的话可能要写很长的代码,容易犯错。
首先类似于八数码问题的棋盘规格,我们考虑使用康拓展开作为状态压缩标记走过的棋盘样式,最多9!种状态。
节点保存棋盘压缩值,步数,棋盘样式。为了方便将每个方格内的四个三角分别对应0,1,2,3,那么a[i][j][k]就可以方便的表示i行j列第k个三角。
每次检查当前头部节点对应的棋盘是否达到了目标状态。这个听别人用的并查集,我没有用,我是dfs染色统计每个颜色联通快的个数,如果每个颜色的个数都<=1,说明当前就是一个合法的状态。关键就是dfs时的方向问题困扰了我,我们常见的方形棋盘一般就是4/8个直观的方形,这个却是三角,其实也不是很难,我们只要dfs三角形的三条边不就好了吗,一共四种三角分类讨论一下也就好了。最后就是有12种移动方式,简单的交换一下就好了,注意提前判断一下是否有不可移动的格子。
  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 bool vis[3630000];
  4 int f[15]={1,1,2,6,24,120,720,5040,40320,362880};
  5 struct node
  6 {
  7     int cal,bs;
  8     char e[10];
  9 };
 10 void change1(node &t,int type)
 11 {
 12     switch(type)
 13     {
 14         case 1:swap(t.e[0],t.e[1]);swap(t.e[1],t.e[2]);break;
 15         case 2:swap(t.e[1],t.e[2]);swap(t.e[0],t.e[1]);break;
 16         case 3:swap(t.e[3],t.e[4]);swap(t.e[4],t.e[5]);break;
 17         case 4:swap(t.e[4],t.e[5]);swap(t.e[3],t.e[4]);break;
 18         case 5:swap(t.e[6],t.e[7]);swap(t.e[7],t.e[8]);break;
 19         case 6:swap(t.e[7],t.e[8]);swap(t.e[6],t.e[7]);break;
 20         case 7:swap(t.e[0],t.e[3]);swap(t.e[3],t.e[6]);break;
 21         case 8:swap(t.e[3],t.e[6]);swap(t.e[0],t.e[3]);break;
 22         case 9:swap(t.e[1],t.e[4]);swap(t.e[4],t.e[7]);break;
 23         case 10:swap(t.e[4],t.e[7]);swap(t.e[1],t.e[4]);break;
 24         case 11:swap(t.e[2],t.e[5]);swap(t.e[5],t.e[8]);break;
 25         case 12:swap(t.e[5],t.e[8]);swap(t.e[2],t.e[5]);break;
 26     }
 27 
 28 }
 29 int cal(node A)
 30 {
 31     int s=0,i,j;
 32     for(i=0;i<9;++i)
 33     {
 34         int c=0;
 35         for(j=i+1;j<9;++j)
 36             if(A.e[j]<A.e[i]) c++;
 37         s+=c*f[8-i];
 38     }
 39     return s;
 40 }
 41 struct nic
 42 {
 43     char color[5];
 44 }a[4][4],b[4][4];
 45 bool mov[2][4];
 46 bool book[5][5][5];
 47 void dfs(int x,int y,int is,char clo)
 48 {
 49   if(x<1||y<1||x>3||y>3||is<0||is>3||b[x][y].color[is]!=clo||book[x][y][is]) return;
 50   b[x][y].color[is]='X';
 51   book[x][y][is]=1;
 52   if(is==0){
 53     dfs(x-1,y,2,clo);
 54     dfs(x,y,1,clo);
 55     dfs(x,y,3,clo);
 56   }
 57   else if(is==1){
 58     dfs(x,y+1,3,clo);
 59     dfs(x,y,0,clo);
 60     dfs(x,y,2,clo);
 61   }
 62   else if(is==2){
 63   dfs(x+1,y,0,clo);
 64   dfs(x,y,1,clo);
 65   dfs(x,y,3,clo);
 66   }
 67   else{
 68     dfs(x,y-1,1,clo);
 69     dfs(x,y,0,clo);
 70     dfs(x,y,2,clo);
 71   }
 72 }
 73 bool ok(node A)
 74 {
 75     int G=0,B=0,R=0,O=0,i,j,k,p=0;
 76     for(i=1;i<=3;++i)
 77         for(j=1;j<=3;++j,p++){
 78         int di=((int)(A.e[p]-'0'))/3+1,dj=((int)(A.e[p]-'0'))%3+1;
 79         for(k=0;k<4;++k)
 80             b[i][j].color[k]=a[di][dj].color[k];
 81         }
 82     for(i=1;i<=3;++i)
 83         for(j=1;j<=3;++j)
 84             for(k=0;k<4;++k)
 85             {
 86               if(b[i][j].color[k]=='G')
 87                 {G++;}
 88               else if(b[i][j].color[k]=='B')
 89                 B++;
 90               else if(b[i][j].color[k]=='R')
 91                 R++;
 92               else if(b[i][j].color[k]=='O')
 93                 O++;
 94               else continue;
 95                 memset(book,0,sizeof(book));
 96                 dfs(i,j,k,b[i][j].color[k]);
 97             }
 98     return (G<=1&&B<=1&&R<=1&&O<=1);
 99 }
100 int bfs()
101 {
102     queue<node>Q;
103     memset(vis,0,sizeof(vis));
104     node t1,t2;
105     t1.cal=0;
106     t1.bs=0;
107     strcpy(t1.e,"012345678");
108     ok(t1);
109     Q.push(t1);
110     while(!Q.empty()){
111         t1=Q.front();Q.pop();
112         if(ok(t1)) {return t1.bs;}
113         if(vis[t1.cal]) continue;
114         vis[t1.cal]=1;
115         for(int i=1;i<=12;++i)
116         {
117            if(i<=6&&mov[0][(i+1)/2]) continue;
118            if(i>6&&mov[1][(i+1)/2-3]) continue;
119             node tmp=t1;
120             tmp.bs++;
121             change1(tmp,i);
122             tmp.cal=cal(tmp);
123             if(!vis[tmp.cal]) Q.push(tmp);
124         }
125     }
126     return -1;
127 }
128 int main()
129 {
130     int T,N,M,i,j,cas=0,n,m,k;
131     int index[4]={0,2,3,1};
132     cin>>T;
133     while(T--){
134         memset(mov,0,sizeof(mov));
135         memset(a,0,sizeof(a));
136         for(i=1;i<=3;++i)
137            for(j=1;j<=3;++j)
138            {
139                for(k=0;k<4;++k)
140                 cin>>a[i][j].color[index[k]];
141             scanf("%d",&m);
142             if(m==1) mov[0][i]=mov[1][j]=1;
143            }
144         printf("Case #%d: %d\n",++cas,bfs());
145     }
146     return 0;
147 }

 

posted @ 2017-08-14 16:00  *zzq  阅读(159)  评论(0编辑  收藏  举报