题目大意

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

  总体思路很简单,Bfs即可,只是需要注意以下几点:

  • memcmp的返回值不一定是-1, 0, 1,而是<0, =0, >0的某个数。这在windows和linux上的效果不一样。
  • 注意:黑白双方交替走棋。
  • 任意一方都必须走一步。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <set>
#include <cassert>
using namespace std; const int MAX_N = 10;
const int N = 4;
const int Dir[4][2] = { {1, 0}, {0, 1}, {-1, 0}, {0, -1} }; struct Node
{
char A[MAX_N][MAX_N];
int Level;
char NextColor; Node()
{
memset(A, 0, sizeof(A));
Level = 0;
} Node operator = (const Node& a)
{
memcpy(A, a.A, sizeof(A));
Level = a.Level;
NextColor = a.NextColor;
return *this;
} bool operator < (const Node& a) const
{
if (NextColor != a.NextColor)
return NextColor == 'B';
else
return memcmp(A, a.A, sizeof(A)) < 0;
} bool operator == (const Node& a) const
{
return NextColor == a.NextColor && memcmp(A, a.A, sizeof(A)) == 0;
} void OPos1(int &oRow1, int &oCol1)
{
for (int row = 1; row <= N; row++)
for (int col = 1; col <= N; col++)
if (A[row][col] == 'O')
{
oRow1 = row;
oCol1 = col;
return;
}
} void OPos2(int &oRow2, int &oCol2)
{
int oRow1, oCol1;
OPos1(oRow1, oCol1);
for (int col = oCol1 + 1; col <= N; col++)
if (A[oRow1][col] == 'O')
{
oRow2 = oRow1;
oCol2 = col;
return;
}
for (int row = oRow1 + 1; row <= N; row++)
for (int col = 1; col <= N; col++)
if (A[row][col] == 'O')
{
oRow2 = row;
oCol2 = col;
return;
}
assert(0);
} bool CanMove1(const int dRow, const int dCol)
{
int oRow1, oCol1;
OPos1(oRow1, oCol1);
int nextRow = oRow1 + dRow, nextCol = oCol1 + dCol;
return A[nextRow][nextCol] == NextColor && nextRow <= N && nextRow >= 1 && nextCol <= N && nextCol >= 1;
} Node GetMove1(int dRow, int dCol)
{
int oRow1, oCol1;
OPos1(oRow1, oCol1);
Node ans = *this;
swap(ans.A[oRow1][oCol1], ans.A[oRow1 + dRow][oCol1 + dCol]);
return ans;
} bool CanMove2(const int dRow, const int dCol)
{
int oRow2, oCol2;
OPos2(oRow2, oCol2);
int nextRow = oRow2 + dRow, nextCol = oCol2 + dCol;
return A[nextRow][nextCol] == NextColor && nextRow <= N && nextRow >= 1 && nextCol <= N && nextCol >= 1;
} Node GetMove2(int dRow, int dCol)
{
int oRow2, oCol2;
OPos2(oRow2, oCol2);
Node ans = *this;
swap(ans.A[oRow2][oCol2], ans.A[oRow2 + dRow][oCol2 + dCol]);
return ans;
} bool Ok()
{
for (int row = 1; row <= N; row++)
{
char st = A[row][1];
bool ok = true;
for (int col = 2; col <= N; col++)
if (A[row][col] != st)
{
ok = false;
break;
}
if (ok)
return true;
}
for (int col = 1; col <= N; col++)
{
char st = A[1][col];
bool ok = true;
for (int row = 2; row <= N; row++)
if (A[row][col] != st)
{
ok = false;
break;
}
if (ok)
return true;
}
char st = A[1][1];
bool ok = true;
for (int i = 2; i <= N; i++)
if (A[i][i] != st)
{
ok = false;
break;
}
if (ok)
return true;
st = A[1][N];
ok = true;
for (int row = 2, col = N - 1; row <= N; row++, col--)
if (A[row][col] != st)
{
ok = false;
break;
}
return ok;
}
};
Node Start; int Bfs()
{
static queue<Node> q;
static set<Node> cache;
Node s1 = Start, s2 = Start;
s1.NextColor = 'B';
s2.NextColor = 'W';
q.push(s1);
q.push(s2);
cache.insert(s1);
cache.insert(s2);
while (!q.empty())
{
Node cur = q.front();
q.pop();
if (!(cur == s1 || cur == s2) && cur.Ok())
return cur.Level;
for (int i = 0; i < 4; i++)
{
if (cur.CanMove1(Dir[i][0], Dir[i][1]))
{
Node next = cur.GetMove1(Dir[i][0], Dir[i][1]);
next.NextColor = (cur.NextColor == 'B' ? 'W' : 'B');
if (!cache.count(next))
{
next.Level = cur.Level + 1;
cache.insert(next);
q.push(next);
}
}
if (cur.CanMove2(Dir[i][0], Dir[i][1]))
{
Node next = cur.GetMove2(Dir[i][0], Dir[i][1]);
next.NextColor = (cur.NextColor == 'B' ? 'W' : 'B');
if (!cache.count(next))
{
next.Level = cur.Level + 1;
cache.insert(next);
q.push(next);
}
}
}
}
return -1;
} int main()
{
for (int i = 1; i <= 4; i++)
scanf("%s", Start.A[i] + 1);
printf("%d\n", Bfs());
return 0;
}

  

luogu2346 四子连棋的更多相关文章

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

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

  2. Codevs p1004 四子连棋

                          四子连棋 题目描述 Description 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向 ...

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

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

  4. codevs 1004 四子连棋

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

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

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

  6. 【洛谷 P2346】四子连棋(状态压缩,搜索)

    其实这题可以直接二进制状压做,1表示黑棋,0表示白棋,另外记录下2个空点的位置就行了. 具体看代码(冗长): #include <iostream> #include <cstdio ...

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

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

  8. codevs1004四子连棋

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

  9. P2346 四子连棋

    P2346 四子连棋 迭代加深++ 题意描述 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向上下左右四个方向移动到相邻的空格,这叫行棋 ...

随机推荐

  1. Redis系列(八)--缓存穿透、雪崩、更新策略

    1.缓存更新策略 1.LRU/LFU/FIFO算法剔除:例如maxmemory-policy 2.超时剔除,过期时间expire,对于一些用户可以容忍延时更新的数据,例如文章简介内容改了几个字 3.主 ...

  2. java虚拟机(五)--垃圾回收机制GC5

    什么样的对象需要回收 如果对象已经死亡了,就可以进行回收,判断方式如下 1).引用计数器:给对象添加一个计数器,有地方引用,就+1,当引用失效,就-1.当计数器为0时,判断对象不能再使用,但是当对象相 ...

  3. ThinkPHP---框架介绍

    (1)什么是框架? ①框架是一堆包含了常量.方法和类等代码集合: ②半成品应用,只包含了项目开发时的底层架构,并不包含业务逻辑: ③包含一些设计模式,例如单例模式,工厂模式,AR(Active Rec ...

  4. MS SQL Server查询 本日、本周、本月、本季度、本年起始时间

    参数声明 declare @beginTime datetime, --查询开始时间 @endTime datetime, --查询结束时间 @queryTimeType tinyint; --查询时 ...

  5. TWaver 3D应用于大型数据中心(续)

    在2014年11月份,我们当时发了一篇有关TWaver HTML5 3D应用于大型数据中心的文章,该blog比较详细的描述一些常用的功能的实现方法,比如:动态添加机柜,告警,温度,湿度等相关的功能的具 ...

  6. HDU - 6264 - Super-palindrome(思维)

    题意: 给出一个字符串,使得所有的奇数连续子串为回文串,输出最小变化次数 思路: 分析过后,只存在两种情况,1全部为一种字母,2形如abab交替类型 对于奇数位和偶数位单独计数,只需计算出奇数位或者偶 ...

  7. linux whereis-查找二进制程序、代码等相关文件路径

    推荐:更多Linux 文件查找和比较 命令关注:linux命令大全 whereis命令用来定位指令的二进制程序.源代码文件和man手册页等相关文件的路径. whereis命令只能用于程序名的搜索,而且 ...

  8. 利用postman进行接口测试并发送带cookie请求的方法

    做web测试的基本上都用用到postman去做一些接口测试,比如测试接口的访问权限,对于某些接口用户A可以访问,用户B不能访问:比如有时需要读取文件的数据.在postman上要实现这样测试,我们就必要 ...

  9. 【BZOJ 1013】球形空间产生器sphere(高斯消元)

    球形空间产生器sphere HYSBZ - 1013 (高斯消元) 原题地址 题意 给出n维的球上的n个点,问原球体球心. 提示 n维球体上两点距离公式\(dist = \sqrt{ (a1-b1)^ ...

  10. 阿里巴巴json包 --------fastjson

    fastjson对null的处理----String str2 = JSONObject.toJSONString(jsonMap, SerializerFeature.WriteMapNullVal ...