题目描述
在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向上下左右四个方向移动到相邻的空格,这叫行棋一步.
黑白双方交替走棋,任意一方可以先走,如果某个时刻使得任意一种颜色的棋子形成四个一线(包括斜线),这样的状态为目标棋局。
输入输出格式
输入格式:
从文件中读入一个4*4的初始棋局,黑棋子用B表示,白棋子用W表示,空格地带用O表示。
输出格式:
用最少的步数移动到目标棋局的步数。
输入输出样例:
输入:
BWBO
WBWB
BWBW
WBWO
输出:
5
分析:
先讲讲我做这道题的悲惨经历,因为我太弱了想了半小时然后写一下卡一下的写出个BFS然后果不其然样例都没过,
然后换了种思路重写了一遍然后在机房3位dalao历经1小时的debug最后终于A了这道题,十分感谢这3位dalao.
接下来进入正题.
思路:
首先这是一道搜索加模拟题这道题是真的要我这个蒟蒻的命,先分析题目由得知我们有一个4*4的棋盘其中有两个字母为“O”的空白
然后在棋盘中其他字母为B(Black)或W(White),然后我们需要像走五子棋一样要么先走白要么先走黑当出现横排出现4格连续的“B”或“W或”竖列出现4格连续的“B”或“W”
亦或是斜着(包含左斜,右斜)出现4格连续的“B”或“W”只要出现其中一种情况就达成了目标情况(就像五子棋一样).
输出最小步数.
方法:
因为是最小步数我们首先考虑BFS显然这道题BFS是行的通的,但是有一点需要注意玩过五子棋都知道黑白谁先手结果可能不一样,因此我们需要跑两边BFS(1.白先手时2.黑先手时)
然后我们需要下一个棋盘的状况,我们可以用到和“八数码难题”一样的更新操作即我们可以先将每个矩阵压成一个字符串当需要判断是否成立目标状况时在变回矩阵判断,
压缩操作:
为什么要这样做,因为每次Map都在变而我们必须要存下每个不同的状况所以我们需要字符串存下每个不同状况.
void compression()
{
change.clear();//在压缩成一个字符串时当然需要将这个字符串清空
for(int i=1;i<=4;i++)//4*4的矩阵
for(int j=1;j<=4;j++)
change.push_back(Map[i][j]);
}
既然有压缩操作那就必须有拆分的操作
拆分操作:
为什么要这么做,由上面的压缩操作可以得到一个全新的棋盘状况但是我们需要判断当前的状况是否符合标准状况的条件但是很显然字符串是无法判断的
所以我们需要将这个字符串再拆分成一个全新的矩阵再用这个矩阵判断是否符合情况
void break_up(string a)
{
posx=1;posy=1;
for(int i=0;i)
{
if(posy==5)
{
posy=1;
posx++;
}
Map[posx][posy]=a[i];
posy++;
}
}
上面都提到了判断操作
相信判断操作大家都会这里就不多做解释了
判断操作:
当符合情况就返回true否则就返回false
可以发现check里我们用的是string w 那就说明再判断前我们一定要将需要判断的字符串拆分成矩阵
bool check(string w)
{
for(int i=1;i<=4;i++)//横竖
{
if(Map[i][1]==Map[i][2]&&Map[i][1]==Map[i][3]&&Map[i][1]==Map[i][4]) return true;
if(Map[1][i]==Map[2][i]&&Map[1][i]==Map[3][i]&&Map[1][i]==Map[4][i]) return true;
}
if(Map[1][4]==Map[2][3]&&Map[1][4]==Map[3][2]&&Map[1][4]==Map[4][1]) return true;//右斜
if(Map[1][1]==Map[2][2]&&Map[1][1]==Map[3][3]&&Map[1][1]==Map[4][4]) return true;//左斜
return false;
}
在贴整段代码之前我还要再BB一两句下面这些话可能对你理解这题的BFS有帮助
1.由题意我们可以知道这题的BFS其实就是将“O”这个点去更新整个棋盘的所有点,我用的是swap这个就是将两个点交换位置至于BFS怎么写看大家的习惯
但是要用swap的小伙伴要注意一下,当搜索不满足情况时因为我们已经交换这两个点所以我们必须再交换回去才能continue(即再swap一次)
2.有题意我们可以得知这题有两个空格“O”谁先走都没有规定因此我们必须写两个for循环这里也许需要思考一下为什么.
3.再有题意可得这是一个像五子棋一样的游戏所以我们必须一黑一白交替走棋(至于谁先我前面已经说了我们要注意这两种情况因为情况可能不同)
由此三点我们可以得出我们的结构体里需要存储的东西
struct Node
{
int x1,y1,x2,y2,t;//x1,y1为第一个空格“O”的位置 x2,y2为第二个“O”的位置
bool order;//借此判断走棋顺序
string s;//存储每一个矩阵压成的字符串
};
接下来我会贴出整段代码:
如果还有点懵的可以看看整段代码让你的思路更清晰
代码:
#include
#include
#include
#include <string>
#include
#include