#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. Altium CAED 国际认证操作题例题(含下载)

    官网介绍页面 https://www.altium.com.cn/certification 共五套操作题 含资料 蓝奏云:https://www.lanzous.com/i2lj1ng 百度网盘:h ...

  2. sqli-labs 下载、安装

    sqli-labs 下载.安装 下载地址:https://github.com/Audi-1/sqli-labs phpstudy:http://down.php.cn/PhpStudy2018021 ...

  3. @JsonFormat时间格式化注解使用

    @JsonFormat注解是一个时间格式化注解,比如我们存储在mysql中的数据是date类型的,当我们读取出来封装在实体类中的时候,就会变成英文时间格式,而不是yyyy-MM-dd HH:mm:ss ...

  4. PAT甲题题解-1041. Be Unique (20)-水题

    博主欢迎转载,但请给出本文链接,我尊重你,你尊重我,谢谢~http://www.cnblogs.com/chenxiwenruo/p/6789189.html特别不喜欢那些随便转载别人的原创文章又不给 ...

  5. Backbone实践案例

    By:软件11 王思伦 2013-10-4 Backbone简述: Backbone基于MVC架构,用于开发重量级Javascript应用的框架. 如上文所述,Backbone包含多种类,但主要包含了 ...

  6. 第四次Scrum meeting

    第四次Scrum meeting 会议内容: 沟通方面:与学霸在线组.学霸手机客户端组进行沟通,了解现阶段各个小组的进度,并针对接口结构方面进行调整 前后端:我们完全可以是不需要界面的,但是为了用户的 ...

  7. Linux读书笔记第三、四章

    第三章 主要内容: 进程和线程 进程的生命周期 进程的创建 进程的终止 1. 进程和线程 进程和线程是程序运行时状态,是动态变化的,进程和线程的管理操作(比如,创建,销毁等)都是有内核来实现的. Li ...

  8. 第二个Sprint冲刺第 九天(燃尽图)

  9. Linux命令学习chroot和chmode

    chroot:chang root http://man.linuxde.net/chroot https://baike.baidu.com/item/chroot 1.限制被CHROOT的使用者所 ...

  10. 【版本管理】自定义git

    Git除了可配置user.name和user.email外,实际上,Git还有很多可配置项. 如 $ git config --global color.ui true,让Git显⽰示颜⾊色,会让命令 ...