【题解】LuoGu2346:四子连棋

版权声明: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.

猜你喜欢

转载自blog.csdn.net/ModestCoder_/article/details/82192645