#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <cstring>
#include <map>
#include <set>
using namespace std; const int maxn = ;
//可移动方向
int dir[][] = { { -, }, { , }, { , }, { , - } };
struct Status {
//last = 1 : 黑子, last = 2 : 白子
//包括把16位3进制转换成一个十进制数的结果hash,移动步数step
int hash, step, last; //hash:为了描述棋子的位置信息,但是不能重复
int map[maxn][maxn];
} Map; /*
* h[1][x]记录黑子放的移动到达的信息
* h[1][x]=false,表示还没有移动这个状态
* h[1][x]=true, 表示之前已经到达过, 不用进队
*/
map<int, bool> h[];
queue<Status> que; //BFS, 队列 void input(); //输入数据
void solve(); //启动函数
bool judge(int r, int c); //判断越界
bool check(Status a); //判断是否满足目标状态
//移动一步,生成新的棋子位置, k 为移动方向
void Move(Status now, int r, int c, int k);
void findSpace(const Status& now, int &r, int &c, int &r2, int &c2); //找到空格的位置
//把此时棋盘的状态, 全部用0,1,2表示每一位的三进制,转换成一个十进制
int getHash(Status a); //对当前棋盘的棋子设置HashCode
void BFS(); //宽搜BFS void input()
{
char s[];
/*
* 把每一位的棋子 换成 空格-0,黑子-1, 白子-2 (三进制)
* 这是一个16位的3进制数, 对应一个十进制数, 然后通过哈希该
* 棋盘的十进制数, 则可找到对应的棋盘状态
*/
for (int i = ; i < maxn; i++)
{
scanf("%s", s);
for (int j = ; j < maxn; j++) {
if (s[j] == 'B') Map.map[i][j] = ;
if (s[j] == 'W') Map.map[i][j] = ;
}
}
} bool judge(int r, int c)
{
return (r >= && r < maxn) && (c >= && c < maxn);
} bool check(Status a)
{
bool flag = true;
//横向连成4个
for (int i = ; i < maxn; i++)
{
flag = true;
for (int j = ; j < maxn - ; j++) {
if (a.map[i][j] != a.map[i][j + ]) {
flag = false;
}
}
if (flag) return true;
} //纵向连成4个
for (int i = ; i < maxn; i++)
{
flag = true;
for (int j = ; j < maxn - ; j++) {
if (a.map[j][i] != a.map[j + ][i]) {
flag = false;
}
}
if (flag) return true;
} flag = true;
for (int i = ; i < maxn - ; i++) {
if (a.map[i][i] != a.map[i + ][i + ]) {
flag = false;
}
}
if (flag) return true; flag = true;
for (int i = maxn - ; i > ; i--) {
if (a.map[i][i] != a.map[i - ][i - ]) {
flag = false;
}
}
if (flag) return true; //都没有连成4子, false
return false;
} //全部用0,1,2表示每一位的三进制,转换成一个十进制
//用了Hash查找
int getHash(Status a)
{
int res = ;
int k = ;
for (int i = ; i < ; i++) {
for (int j = ; j < ; j++) {
res += a.map[i][j] * k;
k *= ;
}
}
return res;
} void findSpace(const Status& now, int &r1, int &c1, int &r2, int &c2)
{
for (int i = ; i < maxn; i++)
{
for (int j = ; j < maxn; j++) {
if (!now.map[i][j])
{
if (r1 == - && c1 == -) {
r1 = i; c1 = j;
}
else {
r2 = i; c2 = j;
}
}
}
}
} /*每移动 一步,都需要对其进行
* 1.是否越界检查
* 2.移动棋子, 并标志移动, 并设置下一次移动的棋子种类
* 3.是否完成目标检查
* 4.未完成 则 设置新棋盘的HashCode
* 5.检查该棋子状态 是否出现过, 没有则入队,并标志为出现过
*移动一步,生成新的棋子位置, k 为移动方向
*/
void Move(Status now, int r, int c, int k)
{
Status tmp = now;
int tmpx = r + dir[k][];
int tmpy = c + dir[k][];
//判断是否越界 || 先后手, 不能两次都移动自己的子
//(如,第一次移动白子,第二次,白子能够移动还移动白子,是错误行为
if (!judge(tmpx, tmpy) || tmp.map[tmpx][tmpy] == tmp.last)
return;
tmp.last = - tmp.last; //取反,上次白子(1), 这次就黑子(2)
swap(tmp.map[tmpx][tmpy], tmp.map[r][c]); //交换棋子和空白位置
tmp.hash = getHash(tmp); //重新设置hashCode
tmp.step++; //移动成功,步数+1
if (check(tmp)) {
printf("%d\n", tmp.step);
exit(); //结束整个程序
}
//表示tmp.last这个种类, 单独的某个棋子 当前的状态-是否移动过
//false-没有移动过,可以入队
if (!h[tmp.last][tmp.hash])
{
h[tmp.last][tmp.hash] = true; //标志此状态已经出现过
que.push(tmp); //入队
}
} void BFS()
{
Map.hash = getHash(Map); //首状态棋盘对应的HashCode
//因为谁先下都行,所以两个棋子都应该入队
Map.last = ;
que.push(Map);
Map.last = ; //黑
que.push(Map); while (!que.empty())
{
Status now;
now = que.front();
que.pop();
int r1 = -, c1 = -, r2 = -, c2 = -;
findSpace(now, r1, c1, r2, c2); //找到空格位置 //一个棋盘有两个空格,所以两个一起来搜索四个方向
for (int k = ; k < maxn; k++) {
Move(now, r1, c1, k);
Move(now, r2, c2, k);
}
}
} void solve()
{
input();
BFS();
} int main()
{
solve();
return ;
}

BFS算法不错的练习~

参考了这篇博客: http://blog.csdn.net/re_cover/article/details/9034219

BFS搜索算法应用_Codevs 1004 四子连棋的更多相关文章

  1. codevs 1004 四子连棋

    1004 四子连棋  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold     题目描述 Description 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白 ...

  2. codevs 1004 四子连棋 BFS、hash判重

    004 四子连棋 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold       题目描述 Description 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋 ...

  3. 【wikioi】1004 四子连棋

    题目链接 算法:BFS //2014-02-05更新 *******************************2013-10-15******************************* ...

  4. CODEVS 1004四子连棋

    [题目描述 Description] 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向上下左右四个方向移动到相邻的空格,这叫行棋一步,黑 ...

  5. CODEVS——T 1004 四子连棋

    http://codevs.cn/problem/1004/  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解  查看运行结果     题目描述 Descr ...

  6. codevs1004四子连棋[BFS 哈希]

    1004 四子连棋   时间限制: 1 s   空间限制: 128000 KB   题目等级 : 黄金 Gold   题目描述 Description 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗 ...

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

    一.写在前面 其实这是一道大水题,而且还出在了数据最水的OJ上,所以实际上这题并没有什么难度.博主写这篇blog主要是想写下一个想法--状态压缩.状态压缩在记录.修改状态以及判重去重等方面有着极高的( ...

  8. codevs1004四子连棋

    1004 四子连棋  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold     题目描述 Description 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白 ...

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

    迭代加深搜索 一.算法简介 迭代加深搜索是在速度上接近广度优先搜索,空间上和深度优先搜索相当的搜索方式.由于在使用过程中引入了深度优先搜索,所以也可以当作深度优先搜索的优化方案. 迭代加深搜索适用于当 ...

随机推荐

  1. golang高性能端口扫描

    前言 最近有个小项目的需要,使用golang写了个端口扫描工具,不得不说golang的效率确实比python快的太多了.在使用一段时间golang之后,感觉有三个方面是优于python的: 一个方面是 ...

  2. fis入门-单文件编译之文件优化(optimize)

    FIS(Front-end Integrated Solution ),是百度的前端集成解决方案.最近几天在研究前端构建的东西,就顺便了解了下,果断各种高大上,可以到FIS官网围观感受一下.如果对fi ...

  3. HTML 背景实例

    71.HTML 背景实例好的背景使站点看上去特别棒.背景(Backgrounds)<body> 拥有两个配置背景的标签.背景可以是颜色或者图像.<body> 标签中的背景颜色( ...

  4. linux下tomcat指定jdk和配置运行参数

    一.指定运行jdk 1)set classpath.sh和catalina.sh中写入: export JAVA_HOME=/usr/local/java/jdk1.8.0_121 export JR ...

  5. debug 在windows下的使用

    debug是什么? debug是一款windows和DOS系统下的一款软件,其最早可追溯到1937年的"马克1号"(具体度娘):早期debug主要在DOS和windows系统中,它 ...

  6. imagick用法!

    https://coderwall.com/p/9hj97w sudo apt-get install imagemagick sudo apt-get install php5-imagick su ...

  7. 20135327郭皓--Linux内核分析第四周 扒开系统调用的三层皮(上)

    Linux内核分析第四周 扒开系统调用的三层皮(上) 郭皓 原创作品转载请注明出处 <Linux内核分析>MOOC课程 http://mooc.study.163.com/course/U ...

  8. 求二维数组联通子数组和的最大值 (联通涂色) beta!

    算法十分臃肿,效率捉鸡,不知用了多少循环,还有bug...任重道远,编程之美. 思想:按行遍历,找出每行的最大子数组.若行间都联通,行最大子数组相加后,再加上独立的正数.若行间不连通,找出较大子路径, ...

  9. 基于 Java Web 的毕业设计选题管理平台--测试报告与用户手册

    一.测试报告 1.兼容性测试 功能 描述 效果 Chrome浏览器 FireFox浏览器 IE浏览器 war 端浏览器 管理员登录 管理员用户登录功能 弹出“登录成功”对话框,进入到毕业设计选题管理平 ...

  10. jvm垃圾回收机制和常见算法

    这是朋友给的面试题里边的,具体地址已经找不到,只能对原作者说声抱歉了: 理论上来讲sun公司只定义了垃圾回收机制规则,而步局限于其实现算法,因此不同厂商生产的虚拟机采用的算法也不尽相同. GC(Gar ...