【宽度优先搜索】神奇的状态压缩 CodeVs1004四子连棋

一、写在前面

其实这是一道大水题,而且还出在了数据最水的OJ上,所以实际上这题并没有什么难度。博主写这篇blog主要是想写下一个想法——状态压缩。状态压缩在记录、修改状态以及判重去重等方面有着极高的(←_←词穷了,诸位大致理解一下就好)效率。博主原本打算在blog介绍一种DP——状态压缩型动态规划,但动笔(键盘??)前,博主突然想起自己前些年写过的一道广搜题,当时在判重方面冥思苦想想出了一种类似状态压缩的方法,开心了好久,于是在此先抛砖引玉为状压DP做个铺垫。

二、题目

Description

 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向上下左右四个方向移动到相邻的空格,这叫行棋一步,黑白双方交替走棋,任意一方可以先走,如果某个时刻使得任意一种颜色的棋子形成四个一线(包括斜线),这样的状态为目标棋局。

Input Description

从文件中读入一个4*4的初始棋局,黑棋子用B表示,白棋子用W表示,空格地带用O表示。

Output Description

用最少的步数移动到目标棋局的步数。

Sample Input

BWBO
WBWB
BWBW
WBWO

Sample Output

5

原题链接→_→:|1004 四子连棋|CODEVS,算法爱好者社区

三、题目分析

大体思路大家都懂,一个中规中矩的广搜没什么好说的,主要来说说状态压缩。我们知道由于不同的棋盘状态经过不同的操作后可能得到同一张棋盘,所以为了节省空间和时间,我们需要进行判重操作——即如果一个棋盘状态已经如果队了,我们不会将其第二次入队。然而如何存储棋盘状态成了一个问题,这时我们就需要用到神奇的状态压缩了。我们发现,一个棋盘中有且仅有三种元素,我们不妨规定0代表空格,1代表白棋,2代表黑棋。如此一来,每张棋盘都被转化成了一个独一无二的三进制数,每个三进制数转化成十进制数就便于我们存储了;而当我们需要使用这些被存储的状态时,我们只需要把十进制再转回三进制即可。如样例棋盘对应的三进制数就是2120121221211210。

四、代码实现

幼年期代码真的辣眼睛,各位看官凑合着看吧_(:з」∠)_

  1 #include<stdio.h>
  2 int map[5][5];
  3 bool vis[44000000];
  4 int q[100000],l,r;
  5 int step[100000];
  6 int col[100000];
  7 int x[3],y[3],mark;
  8 void input()
  9 {
 10     char k[10];
 11     int p,q;
 12     for(p=1;p<=4;p++)
 13     {
 14         scanf("%s",k);
 15         for(q=0;q<=3;q++)
 16         {
 17             if(k[q]=='O')
 18             {
 19                 map[p][q+1]=0;
 20             }
 21             if(k[q]=='W')
 22             {
 23                 map[p][q+1]=1;
 24             }
 25             if(k[q]=='B')
 26             {
 27                 map[p][q+1]=2;
 28             }
 29         }
 30     }
 31 }
 32 int trans()//把棋盘转成十进制数存储 
 33 {
 34     int i,j;
 35     int cnt=1,ans=0;
 36     for(i=4;i>=1;i--)
 37     {
 38         for(j=4;j>=1;j--)
 39         {
 40             ans+=map[i][j]*cnt;
 41             cnt*=3;
 42         }
 43     }
 44     return ans;
 45 }
 46 bool check()
 47 {
 48     if(map[1][1]==map[2][2]&&map[2][2]==map[3][3]&&map[3][3]==map[4][4])return true;
 49     if(map[1][4]==map[2][3]&&map[2][3]==map[3][2]&&map[3][2]==map[4][1])return true;
 50     int i;
 51     for(i=1;i<=4;i++)
 52     {
 53         if(map[1][i]==map[2][i]&&map[2][i]==map[3][i]&&map[3][i]==map[4][i])return true;
 54         if(map[i][1]==map[i][2]&&map[i][2]==map[i][3]&&map[i][3]==map[i][4])return true;
 55     }
 56     return false;
 57 }
 58 void reset(int num)//把十进制数转成三进制还原棋盘 
 59 {
 60     int i,j;
 61     for(i=4;i>=1;i--)
 62     {
 63         for(j=4;j>=1;j--)
 64         {
 65             map[i][j]=num%3;
 66             num/=3;
 67         }
 68     }
 69 }
 70 void bfs()
 71 {
 72     int i,j;
 73     int num;
 74     while(l<=r)
 75     {
 76         mark=0;
 77         reset(q[l]);
 78         if(check())
 79         {
 80             return;
 81         }
 82         for(i=1;i<=4;i++)
 83         {
 84             for(j=1;j<=4;j++)
 85             {
 86                 if(!map[i][j])
 87                 {
 88                     x[++mark]=i;
 89                     y[mark]=j;
 90                 }
 91             }
 92         }
 93         if((x[1]!=1&&col[l]==0)||(x[1]!=1&&map[x[1]-1][y[1]]==3-col[l]))
 94         {
 95             map[x[1]][y[1]]=map[x[1]-1][y[1]];
 96             map[x[1]-1][y[1]]=0;
 97             num=trans();
 98             if(vis[num])
 99             {
100                 map[x[1]-1][y[1]]=map[x[1]][y[1]];
101                 map[x[1]][y[1]]=0;
102             }
103             else 
104             {
105                 vis[num]=true;
106                 q[++r]=num;
107                 step[r]=step[l]+1;
108                 col[r]=map[x[1]][y[1]];
109                 map[x[1]-1][y[1]]=map[x[1]][y[1]];
110                 map[x[1]][y[1]]=0;
111             }
112         }
113         if(col[l]==0||map[x[1]+1][y[1]]==3-col[l])
114         {
115             map[x[1]][y[1]]=map[x[1]+1][y[1]];
116             map[x[1]+1][y[1]]=0;
117             num=trans();
118             if(vis[num])
119             {
120                 map[x[1]+1][y[1]]=map[x[1]][y[1]];
121                 map[x[1]][y[1]]=0;
122             }
123             else 
124             {
125                 vis[num]=true;
126                 q[++r]=num;
127                 step[r]=step[l]+1;
128                 col[r]=map[x[1]][y[1]];
129                 map[x[1]+1][y[1]]=map[x[1]][y[1]];
130                 map[x[1]][y[1]]=0;
131             }
132         }
133         if((y[1]!=1&&col[l]==0)||(y[1]!=1&&map[x[1]][y[1]-1]==3-col[l]))
134         {
135             map[x[1]][y[1]]=map[x[1]][y[1]-1];
136             map[x[1]][y[1]-1]=0;
137             num=trans();
138             if(vis[num])
139             {
140                 map[x[1]][y[1]-1]=map[x[1]][y[1]];
141                 map[x[1]][y[1]]=0;
142             }
143             else 
144             {
145                 vis[num]=true;
146                 q[++r]=num;
147                 step[r]=step[l]+1;
148                 col[r]=map[x[1]][y[1]];
149                 map[x[1]][y[1]-1]=map[x[1]][y[1]];
150                 map[x[1]][y[1]]=0;
151             }
152         }
153         if(col[l]==0||map[x[1]][y[1]+1]==3-col[l])
154         {
155             map[x[1]][y[1]]=map[x[1]][y[1]+1];
156             map[x[1]][y[1]+1]=0;
157             num=trans();
158             if(vis[num])
159             {
160                 map[x[1]][y[1]+1]=map[x[1]][y[1]];
161                 map[x[1]][y[1]]=0;
162             }
163             else 
164             {
165                 vis[num]=true;
166                 q[++r]=num;
167                 step[r]=step[l]+1;
168                 col[r]=map[x[1]][y[1]];
169                 map[x[1]][y[1]+1]=map[x[1]][y[1]];
170                 map[x[1]][y[1]]=0;
171             }
172         }
173         if((x[2]!=1&&col[l]==0)||(x[2]!=1&&map[x[2]-1][y[2]]==3-col[l]))
174         {
175             map[x[2]][y[2]]=map[x[2]-1][y[2]];
176             map[x[2]-1][y[2]]=0;
177             num=trans();
178             if(vis[num])
179             {
180                 map[x[2]-1][y[2]]=map[x[2]][y[2]];
181                 map[x[2]][y[2]]=0;
182             }
183             else 
184             {
185                 vis[num]=true;
186                 q[++r]=num;
187                 step[r]=step[l]+1;
188                 col[r]=map[x[2]][y[2]];
189                 map[x[2]-1][y[2]]=map[x[2]][y[2]];
190                 map[x[2]][y[2]]=0;
191             }
192         }
193         if(col[l]==0||map[x[2]+1][y[2]]==3-col[l])
194         {
195             map[x[2]][y[2]]=map[x[2]+1][y[2]];
196             map[x[2]+1][y[2]]=0;
197             num=trans();
198             if(vis[num])
199             {
200                 map[x[2]+1][y[2]]=map[x[2]][y[2]];
201                 map[x[2]][y[2]]=0;
202             }
203             else 
204             {
205                 vis[num]=true;
206                 q[++r]=num;
207                 step[r]=step[l]+1;
208                 col[r]=map[x[2]][y[2]];
209                 map[x[2]+1][y[2]]=map[x[2]][y[2]];
210                 map[x[2]][y[2]]=0;
211             }
212         }
213         if((y[2]!=1&&col[l]==0)||(y[2]!=1&&map[x[2]][y[2]-1]==3-col[l]))
214         {
215             map[x[2]][y[2]]=map[x[2]][y[2]-1];
216             map[x[2]][y[2]-1]=0;
217             num=trans();
218             if(vis[num])
219             {
220                 map[x[2]][y[2]-1]=map[x[2]][y[2]];
221                 map[x[2]][y[2]]=0;
222             }
223             else 
224             {
225                 vis[num]=true;
226                 q[++r]=num;
227                 step[r]=step[l]+1;
228                 col[r]=map[x[2]][y[2]];
229                 map[x[2]][y[2]-1]=map[x[2]][y[2]];
230                 map[x[2]][y[2]]=0;
231             }
232         }
233         if(col[l]==0||map[x[2]][y[2]+1]==3-col[l])
234         {
235             map[x[2]][y[2]]=map[x[2]][y[2]+1];
236             map[x[2]][y[2]+1]=0;
237             num=trans();
238             if(vis[num])
239             {
240                 map[x[2]][y[2]+1]=map[x[2]][y[2]];
241                 map[x[2]][y[2]]=0;
242             }
243             else 
244             {
245                 vis[num]=true;
246                 q[++r]=num;
247                 step[r]=step[l]+1;
248                 col[r]=map[x[2]][y[2]];
249                 map[x[2]][y[2]+1]=map[x[2]][y[2]];
250                 map[x[2]][y[2]]=0;
251             }
252         }
253         l++;
254     }
255 }
256 int main()
257 {
258     int i,j;
259     input();
260     int num=trans();
261     vis[num]=true;
262     l=1;
263     r=1;
264     q[1]=num;
265     bfs();
266     printf("%d",step[l]);
267     return 0;
268 }
CodeVs1004 四子连棋

弱弱地说一句,本蒟蒻码字也不容易,转载请注明出处http://www.cnblogs.com/Maki-Nishikino/p/5991570.html

posted @ 2016-10-24 01:07  Maki_Nishikino  阅读(462)  评论(0编辑  收藏  举报