版权声明:Fashion Education https://blog.csdn.net/ModestCoder_/article/details/82192645
原题传送门
题目描述
在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向上下左右四个方向移动到相邻的空格,这叫行棋一步,黑白双方交替走棋,任意一方可以先走,如果某个时刻使得任意一种颜色的棋子形成四个一线(包括斜线),这样的状态为目标棋局。
● ○ ●
○ ● ○ ●
● ○ ● ○
○ ● ○
输入输出格式
输入格式:
从文件中读入一个4*4的初始棋局,黑棋子用B表示,白棋子用W表示,空格地带用O表示。
输出格式:
用最少的步数移动到目标棋局的步数。
输入输出样例
输入样例
BWBO
WBWB
BWBW
WBWO
输出样例
5
【题解】
本题是一道裸的bfs
移动棋子,就是把棋子跟空白交换,等价于移动空白
因为空白只有两个,所以这样一来,我们就简化了方案数,把每层14*4种可能优化到了2*4种可能
又发现这个棋盘很小,只有4*4,所以可以给队列中每个元素配置一个棋盘,可以不用深搜了(本题dfs目测会Tle),而且也不会Mle
还有需要注意的是:黑白棋先手任意,但需交替移动,我就因为这个地方没注意wa了,不过只需多判断一下
我coding时瞎琢磨出一种有趣的玩法,使我的code不堪入目(这个词好像可以用在这里),勿喷,谢谢。
Code:
type
ar = array[1..4,1..4] of longint;
node = record
x,y:longint;
end;
var
q:array[0..100000] of record
k1,k2,last:node;//k1,k2表示两个空白的状态,last表示上次走的是哪里
cnt:longint;//cnt表示步数
a:ar;//a数组记录状态
end;
a:ar;
ch:char;
dx:array[1..4] of longint = (-1,0,0,1);
dy:array[1..4] of longint = (0,-1,1,0);
n,i,j,head,tail,x,y:longint;
function check(a:ar):boolean;//判断是否四子连棋
var
i:longint;
begin
for i := 1 to n do
begin
if (a[i][1] = a[i][2]) and (a[i][1] = a[i][3]) and (a[i][1] = a[i][4]) then exit(true);
if (a[1][i] = a[2][i]) and (a[1][i] = a[3][i]) and (a[1][i] = a[4][i]) then exit(true);
end;
if (a[1][1] = a[2][2]) and (a[1][1] = a[3][3]) and (a[1][1] = a[4][4]) then exit(true);
if (a[1][4] = a[2][3]) and (a[1][4] = a[3][2]) and (a[1][4] = a[4][1]) then exit(true);
exit(false);
end;
procedure swap(var x,y:longint);
var
tmp:longint;
begin
tmp := x; x := y; y := tmp;
end;
begin
n := 4;
for i := 1 to n do
begin
for j := 1 to n do
begin
read(ch);//W为1,B为0,空白为2
if ch = 'W' then a[i][j] := 1 else
if ch = 'O' then
begin
a[i][j] := 2;
if q[1].k1.x = 0 then
begin
q[1].k1.x := i;
q[1].k1.y := j;
end else
begin
q[1].k2.x := i;
q[1].k2.y := j;
end;
end;
end;
readln;
end;
tail := 1; q[1].a := a;
while head < tail do//做两遍,每个空白都要做一遍
begin
inc(head);
for i := 1 to 4 do
begin
x := q[head].k1.x + dx[i];
y := q[head].k1.y + dy[i];
if (x > 0) and (y > 0) and (x <= n) and (y <= n) then
if (x <> q[head].last.x) or (y <> q[head].last.y) then
if (x <> q[head].k2.x) or (y <> q[head].k2.y) then
if q[head].a[x][y] <> q[head].a[q[head].last.x][q[head].last.y] then
begin
inc(tail);
q[tail].k1.x := x;
q[tail].k1.y := y;
q[tail].last.x := q[head].k1.x;
q[tail].last.y := q[head].k1.y;
q[tail].cnt := q[head].cnt + 1;
q[tail].k2 := q[head].k2;
q[tail].a := q[head].a;
swap(q[tail].a[x][y],q[tail].a[q[head].k1.x][q[head].k1.y]);
if check(q[tail].a) then
begin
writeln(q[tail].cnt);
halt;
end;
end;
end;
for i := 1 to 4 do
begin
x := q[head].k2.x + dx[i];
y := q[head].k2.y + dy[i];
if (x > 0) and (y > 0) and (x <= n) and (y <= n) then
if (x <> q[head].last.x) or (y <> q[head].last.y) then
if (x <> q[head].k1.x) or (y <> q[head].k1.y) then
if q[head].a[x][y] <> q[head].a[q[head].last.x][q[head].last.y] then
begin
inc(tail);
q[tail].k2.x := x;
q[tail].k2.y := y;
q[tail].last.x := q[head].k2.x;
q[tail].last.y := q[head].k2.y;
q[tail].cnt := q[head].cnt + 1;
q[tail].k1 := q[head].k1;
q[tail].a := q[head].a;
swap(q[tail].a[x][y],q[tail].a[q[head].k2.x][q[head].k2.y]);
if check(q[tail].a) then
begin
writeln(q[tail].cnt);
halt;
end;
end;
end;
end;
end.