【宽度优先搜索】神奇的状态压缩 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

时间: 2024-10-16 06:35:27

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

迭代加深搜索[codevs1004 四子连棋]

迭代加深搜索 一.算法简介 迭代加深搜索是在速度上接近广度优先搜索,空间上和深度优先搜索相当的搜索方式.由于在使用过程中引入了深度优先搜索,所以也可以当作深度优先搜索的优化方案. 迭代加深搜索适用于当搜索深度没有明确上限的情况. 例如上图的一棵搜索树,在进行深度优先搜索前先规定好这次搜索的最大深度dep,当搜索到达dep却还没搜索到结果时回溯. 之后不断加大搜索深度,重新搜索,直到找到结果为止.虽然这样搜索次数会累计很多次,但每一次搜索的范围和下一次搜索的范围相比微不足道,所以整体搜索速度不会受

codevs1004四子连棋[BFS 哈希]

1004 四子连棋  时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向上下左右四个方向移动到相邻的空格,这叫行棋一步,黑白双方交替走棋,任意一方可以先走,如果某个时刻使得任意一种颜色的棋子形成四个一线(包括斜线),这样的状态为目标棋局. ● ○ ●   ○ ● ○ ● ● ○ ● ○ ○ ● ○   输入描述 Inpu

【日常学习】【迭代加深搜索+哈希】codevs1004 四子连棋题解

转载请注明出处 [ametake版权所有]http://blog.csdn.net/ametake 题目描述 Description 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向上下左右四个方向移动到相邻的空格,这叫行棋一步,黑白双方交替走棋,任意一方可以先走,如果某个时刻使得任意一种颜色的棋子形成四个一线(包括斜线),这样的状态为目标棋局. ● ○ ●   ○ ● ○ ● ● ○ ● ○ ○ ● ○   输入描述 Input

挑战程序2.1.5 穷竭搜索&gt;&gt;宽度优先搜索(练POJ3669)

先对比一下DFS和BFS         深度优先搜索DFS                                   宽度优先搜索BFS 明显可以看出搜索顺序不同. DFS是搜索单条路径到底部,再回溯. BFS是搜索近的状态,直到底部,一般在求解最短路径或者最短步数上应用. BFS要用到队列呢.. 队列的用法看一看http://blog.csdn.net/cindywry/article/details/51919282 练习题系列--------------------- 题目:p

广度/宽度优先搜索(BFS)详解

广度/宽度优先搜索(BFS) [算法入门] 1.前言 广度优先搜索(也称宽度优先搜索,缩写BFS,以下采用广度来描述)是连通图的一种遍历策略.因为它的思想是从一个顶点V0开始,辐射状地优先遍历其周围较广的区域,故得名. 一般可以用它做什么呢?一个 广度/宽度优先搜索(BFS) 算法导论里边会给出不少严格的证明,我想尽量写得通俗一点,因此采用一些直观的讲法来伪装成证明,关键的point能够帮你get到就好. 2.图的概念 刚刚说的广度优先搜索是连通图的一种遍历策略,那就有必要将图先简单解释一下.

宽度优先搜索(BFS)

宽度优先搜索,又称为广度优先搜索,简称BFS 搜索过程:从初始结点开始,逐层向下扩展,即第n层搜索未完成,不得进入下一层搜索 一.初始结点入队,进入循环 二.取出队列的第一个元素 三.判断该结点是不是目标结点,如果是目标结点,则问题解决,跳出循环 四.如果该结点不是目标结点,判断其是否能够扩展,若不能,跳到步骤二 五.如果该结点能扩展,将其子结点放入队列的尾部 六.跳到步骤二 用一个经典的例子(走迷宫)来感受下 给定一个二维数组 int a[10][10] = {0 , 1 , 0 , 0 ,

算法7-4:宽度优先搜索

宽度优先搜索的基本思想就是先将源点添加到一个队列中, 每次从队列中取出一个顶点,将该顶点的邻居顶点中没有拜访过的顶点都添加到队列中,最后直到队列消耗完毕为止. 应用 宽度优先搜索可以解决最短路径问题.而最短路径算法在互联网中应用非常广泛,尤其是路由这块.因为路由追求的是高效,所以每个路由路径都是通过最短路径计算出来的.如果没有最短路径算法,我们可能就享受不到这么快的网速了. 另外,宽度优先搜索在快递行业也会用到,用于计算最短路径. 代码 import java.util.Stack; /** *

宽度优先搜索

Breadth First Search 宽度优先搜索算法(又称广度优先搜索)是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型.Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想.其别名又叫BFS,属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果.换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止. 与树的层序遍历一样 遍历结果为 1 2 3 4 5 6 .....21 22 操作: 根节点入队: wh

(总结)宽度优先搜索(Breadth First Search)

ACM入门最经典的开局一般都是宽搜. 宽度优先搜索(以下均简称bfs)一般用于树和图的搜索,在ACM中属于比较基础的技巧,因此需要非常熟练的掌握. 那么从最基础的bfs开始讲起.在一个迷宫中,有一个起点和一个终点(出口),和一些障碍物(无法通过). 比如下图