【宽度优先搜索】神奇的状态压缩 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。
四、代码实现
幼年期代码真的辣眼睛,各位看官凑合着看吧_(:з」∠)_
#include<stdio.h>
int map[][];
bool vis[];
int q[],l,r;
int step[];
int col[];
int x[],y[],mark;
void input()
{
char k[];
int p,q;
for(p=;p<=;p++)
{
scanf("%s",k);
for(q=;q<=;q++)
{
if(k[q]=='O')
{
map[p][q+]=;
}
if(k[q]=='W')
{
map[p][q+]=;
}
if(k[q]=='B')
{
map[p][q+]=;
}
}
}
}
int trans()//把棋盘转成十进制数存储
{
int i,j;
int cnt=,ans=;
for(i=;i>=;i--)
{
for(j=;j>=;j--)
{
ans+=map[i][j]*cnt;
cnt*=;
}
}
return ans;
}
bool check()
{
if(map[][]==map[][]&&map[][]==map[][]&&map[][]==map[][])return true;
if(map[][]==map[][]&&map[][]==map[][]&&map[][]==map[][])return true;
int i;
for(i=;i<=;i++)
{
if(map[][i]==map[][i]&&map[][i]==map[][i]&&map[][i]==map[][i])return true;
if(map[i][]==map[i][]&&map[i][]==map[i][]&&map[i][]==map[i][])return true;
}
return false;
}
void reset(int num)//把十进制数转成三进制还原棋盘
{
int i,j;
for(i=;i>=;i--)
{
for(j=;j>=;j--)
{
map[i][j]=num%;
num/=;
}
}
}
void bfs()
{
int i,j;
int num;
while(l<=r)
{
mark=;
reset(q[l]);
if(check())
{
return;
}
for(i=;i<=;i++)
{
for(j=;j<=;j++)
{
if(!map[i][j])
{
x[++mark]=i;
y[mark]=j;
}
}
}
if((x[]!=&&col[l]==)||(x[]!=&&map[x[]-][y[]]==-col[l]))
{
map[x[]][y[]]=map[x[]-][y[]];
map[x[]-][y[]]=;
num=trans();
if(vis[num])
{
map[x[]-][y[]]=map[x[]][y[]];
map[x[]][y[]]=;
}
else
{
vis[num]=true;
q[++r]=num;
step[r]=step[l]+;
col[r]=map[x[]][y[]];
map[x[]-][y[]]=map[x[]][y[]];
map[x[]][y[]]=;
}
}
if(col[l]==||map[x[]+][y[]]==-col[l])
{
map[x[]][y[]]=map[x[]+][y[]];
map[x[]+][y[]]=;
num=trans();
if(vis[num])
{
map[x[]+][y[]]=map[x[]][y[]];
map[x[]][y[]]=;
}
else
{
vis[num]=true;
q[++r]=num;
step[r]=step[l]+;
col[r]=map[x[]][y[]];
map[x[]+][y[]]=map[x[]][y[]];
map[x[]][y[]]=;
}
}
if((y[]!=&&col[l]==)||(y[]!=&&map[x[]][y[]-]==-col[l]))
{
map[x[]][y[]]=map[x[]][y[]-];
map[x[]][y[]-]=;
num=trans();
if(vis[num])
{
map[x[]][y[]-]=map[x[]][y[]];
map[x[]][y[]]=;
}
else
{
vis[num]=true;
q[++r]=num;
step[r]=step[l]+;
col[r]=map[x[]][y[]];
map[x[]][y[]-]=map[x[]][y[]];
map[x[]][y[]]=;
}
}
if(col[l]==||map[x[]][y[]+]==-col[l])
{
map[x[]][y[]]=map[x[]][y[]+];
map[x[]][y[]+]=;
num=trans();
if(vis[num])
{
map[x[]][y[]+]=map[x[]][y[]];
map[x[]][y[]]=;
}
else
{
vis[num]=true;
q[++r]=num;
step[r]=step[l]+;
col[r]=map[x[]][y[]];
map[x[]][y[]+]=map[x[]][y[]];
map[x[]][y[]]=;
}
}
if((x[]!=&&col[l]==)||(x[]!=&&map[x[]-][y[]]==-col[l]))
{
map[x[]][y[]]=map[x[]-][y[]];
map[x[]-][y[]]=;
num=trans();
if(vis[num])
{
map[x[]-][y[]]=map[x[]][y[]];
map[x[]][y[]]=;
}
else
{
vis[num]=true;
q[++r]=num;
step[r]=step[l]+;
col[r]=map[x[]][y[]];
map[x[]-][y[]]=map[x[]][y[]];
map[x[]][y[]]=;
}
}
if(col[l]==||map[x[]+][y[]]==-col[l])
{
map[x[]][y[]]=map[x[]+][y[]];
map[x[]+][y[]]=;
num=trans();
if(vis[num])
{
map[x[]+][y[]]=map[x[]][y[]];
map[x[]][y[]]=;
}
else
{
vis[num]=true;
q[++r]=num;
step[r]=step[l]+;
col[r]=map[x[]][y[]];
map[x[]+][y[]]=map[x[]][y[]];
map[x[]][y[]]=;
}
}
if((y[]!=&&col[l]==)||(y[]!=&&map[x[]][y[]-]==-col[l]))
{
map[x[]][y[]]=map[x[]][y[]-];
map[x[]][y[]-]=;
num=trans();
if(vis[num])
{
map[x[]][y[]-]=map[x[]][y[]];
map[x[]][y[]]=;
}
else
{
vis[num]=true;
q[++r]=num;
step[r]=step[l]+;
col[r]=map[x[]][y[]];
map[x[]][y[]-]=map[x[]][y[]];
map[x[]][y[]]=;
}
}
if(col[l]==||map[x[]][y[]+]==-col[l])
{
map[x[]][y[]]=map[x[]][y[]+];
map[x[]][y[]+]=;
num=trans();
if(vis[num])
{
map[x[]][y[]+]=map[x[]][y[]];
map[x[]][y[]]=;
}
else
{
vis[num]=true;
q[++r]=num;
step[r]=step[l]+;
col[r]=map[x[]][y[]];
map[x[]][y[]+]=map[x[]][y[]];
map[x[]][y[]]=;
}
}
l++;
}
}
int main()
{
int i,j;
input();
int num=trans();
vis[num]=true;
l=;
r=;
q[]=num;
bfs();
printf("%d",step[l]);
return ;
}
CodeVs1004 四子连棋
弱弱地说一句,本蒟蒻码字也不容易,转载请注明出处http://www.cnblogs.com/Maki-Nishikino/p/5991570.html
【宽度优先搜索】神奇的状态压缩 CodeVs1004四子连棋的更多相关文章
- 迭代加深搜索[codevs1004 四子连棋]
迭代加深搜索 一.算法简介 迭代加深搜索是在速度上接近广度优先搜索,空间上和深度优先搜索相当的搜索方式.由于在使用过程中引入了深度优先搜索,所以也可以当作深度优先搜索的优化方案. 迭代加深搜索适用于当 ...
- codevs1004四子连棋[BFS 哈希]
1004 四子连棋 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗 ...
- codevs1004四子连棋
1004 四子连棋 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白 ...
- codevs1004 四子连棋
题目描述 Description 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向上下左右四个方向移动到相邻的空格,这叫行棋一步,黑白双 ...
- 挑战程序2.1.5 穷竭搜索>>宽度优先搜索
先对比一下DFS和BFS 深度优先搜索DFS 宽度优先搜索BFS 明显可以看出搜索顺序不同. DFS是搜索单条路径到 ...
- 【算法入门】广度/宽度优先搜索(BFS)
广度/宽度优先搜索(BFS) [算法入门] 1.前言 广度优先搜索(也称宽度优先搜索,缩写BFS,以下采用广度来描述)是连通图的一种遍历策略.因为它的思想是从一个顶点V0开始,辐射状地优先遍历其周围较 ...
- BFS算法的优化 双向宽度优先搜索
双向宽度优先搜索 (Bidirectional BFS) 算法适用于如下的场景: 无向图 所有边的长度都为 1 或者长度都一样 同时给出了起点和终点 以上 3 个条件都满足的时候,可以使用双向宽度优先 ...
- [宽度优先搜索] FZU-2150 Fire Game
Fat brother and Maze are playing a kind of special (hentai) game on an N*M board (N rows, M columns) ...
- 【BFS宽度优先搜索】
一.求所有顶点到s顶点的最小步数 //BFS宽度优先搜索 #include<iostream> using namespace std; #include<queue> # ...
随机推荐
- imac上php环境php+apache+mysql
---恢复内容开始--- Mac OS X系统已预装集成了Apache+php,但是在新的系统中苹果取消了图形界面,所以只能从命令行开启了. 启用apache: 打开终端 在终端中可以查看集成的php ...
- SpringMVC下的Shiro权限框架的使用
SpringMVC+Shiro权限管理 博文目录 权限的简单描述 实例表结构及内容及POJO Shiro-pom.xml Shiro-web.xml Shiro-MyShiro-权限认证,登录认证层 ...
- windows bat 批处理 !vm 合并快播文件
今天简单的写了一个bat批处理文件 用来处理快播的p2p的文件,一般回事这样的目录 你可以下载如下代码 @echo off for /r %%a in (.) do ( echo %%a cd %%a ...
- buddy算法
buddy算法是用来做内存管理的经典算法,目的是为了解决内存的外碎片.避免外碎片的方法有两种: 1,利用分页单元把一组非连续的空闲页框映射到非连续的线性地址区间. 2,开发适当的技术来记录现存的空闲连 ...
- 【iCore3 双核心板】例程二十三:LAN_HTTP实验——网页服务器
实验指导书及代码包下载: http://pan.baidu.com/s/1getgyKr iCore3 购买链接: https://item.taobao.com/item.htm?id=524229 ...
- HDU 4358 Boring counting(莫队+DFS序+离散化)
Boring counting Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 98304/98304 K (Java/Others) ...
- Linux内核设计第五周——扒开系统调用三层皮(下)
Linux内核设计第五周 ——扒开系统调用三层皮(下) 一.知识点总结 1.给MenuOS增加新的命令的步骤 更新menu代码到最新版 test.c中main函数里,增加MenuConfig() 增加 ...
- 【行业交流】2016 TiD质量竞争力大会——移动互联网测试到质量的转变之路
◆版权声明:本文出自胖喵~的博客,转载必须注明出处. 转载请注明出处:http://www.cnblogs.com/by-dream/p/5691233.html TiD质量大会在北京召开,有幸去参加 ...
- frameset
- 部署移动BI必须要考虑的五大因素
随着大屏智能手机和平板电脑的普及,商业智能分析应用程序也需要移动化.由于用户并不会长时间在办公桌前工作.在新的设备以及新的用户的共同促进下,移动BI即将成为主流. 但是,所有人都应该清楚这样一个事实: ...