Codevs P1004 四子连棋

本文提供了一个解决四子连棋问题的算法,通过广度优先搜索(BFS)来找出最少步数到达目标棋局的方法。该算法考虑棋盘初始状态,通过移动黑白棋子以形成四子一线的目标局面,输出最少需要的步数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Codevs p1004四子连棋


首先说明,由于本人实力低下,所以代码极其冗长。。。。


题目描述 Description

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

●|○|●|空|
○|●|○| ●|
●|○|●| ○|
○|●|○|空|


输入描述 Input Description

从文件中读入一个4*4的初始棋局,黑棋子用B表示,白棋子用W表示,空格地带用O表示。
输出描述 Output Description
用最少的步数移动到目标棋局的步数。


样例输入 Sample Input

BWBO
WBWB
BWBW
WBWO


样例输出 Sample Output

5

分析

直接进行bfs,当第一次找到符合题意的解时便退出程序。肯定是最少步数。

代码如下(实力有限)

program p1004;
const dx:array[1..4] of integer=(1,0,-1,0);
      dy:array[1..4] of integer=(0,1,0,-1);
type ar=array[1..4,1..4] of longint;
var can:array[1..100000] of ar;
    queue:array[1..100000] of record
                               x1,y1,x2,y2,step,pre:longint;
                               now:ar;
                              end;
    ch:char;
    form:ar;
    flag:boolean;
    i,j,k,head,rear,sum:longint;
function complete(x,y:longint):boolean;
var i,j:longint;
    flag:boolean;
begin
 flag:=true;
 for i:=1 to 4 do
  begin
   if form[x,i]<>form[x,y]
    then
     begin
      flag:=false;
      break;
     end;
  end;
 if flag then exit(true);
 flag:=true;
 for i:=1 to 4 do
  begin
   if form[i,y]<>form[x,y]
    then
     begin
      flag:=false;
      break;
     end;
  end;
 if flag then exit(true);
 flag:=true;
 if x+y=5
   then
    begin
     for i:=1 to 4 do
      begin
       if form[i,5-i]<>form[x,y]
        then
         begin
          flag:=false;
          break;
         end;
      end;
     if flag then exit(true);
    end;
 flag:=true;
 if x=y
  then
   begin
    for i:=1 to 4 do
     begin
      if form[i,i]<>form[x,y]
       then
        begin
         flag:=false;
         break;
        end;
     end;
    if flag then exit(true);
   end;
 exit(false);
end;

function same:boolean;
var i,j,k:longint;
    flag:boolean;
begin
 for k:=1 to sum do
  begin
   flag:=false;
   for i:=1 to 4 do
    begin
     for j:=1 to 4 do
      if form[i,j]<>can[k,i,j]
       then
        begin
         flag:=true;
         break;
        end;
     if flag then break;
    end;
   if not flag then exit(true);
  end;
 exit(false);
end;

procedure bfs;
var x,y,k:longint;
begin
 while head<=rear do
  begin
   for k:=1 to 4  do
    begin
     x:=queue[head].x1+dx[k];
     y:=queue[head].y1+dy[k];
     form:=queue[head].now;
     if (x>0) and (x<=4) and (y>0) and (y<=4) and (form[x,y]<>queue[head].pre)
      then
       begin
        form[queue[head].x1,queue[head].y1]:=form[x,y];
        form[x,y]:=0;
        if complete(queue[head].x1,queue[head].y1)
         then
          begin
           writeln(queue[head].step+1);
           exit;
          end;
        if not same
         then
          begin
           inc(rear);
           queue[rear].x1:=x;
           queue[rear].y1:=y;
           queue[rear].x2:=queue[head].x2;
           queue[rear].y2:=queue[head].y2;
           queue[rear].pre:=form[queue[head].x1,queue[head].y1];
           queue[rear].now:=form;
           queue[rear].step:=queue[head].step+1;
           inc(sum);
           can[sum]:=form;
          end;
       end;
    end;
   for k:=1 to 4  do
    begin
     x:=queue[head].x2+dx[k];
     y:=queue[head].y2+dy[k];
     form:=queue[head].now;
     if (x>0) and (x<=4) and (y>0) and (y<=4) and (form[x,y]<>queue[head].pre)
      then
       begin
        form[queue[head].x2,queue[head].y2]:=form[x,y];
        form[x,y]:=0;
        if complete(queue[head].x2,queue[head].y2)
         then
          begin
           writeln(queue[head].step+1);
           exit;
          end;
        if not same
         then
          begin
           inc(rear);
           queue[rear].x1:=queue[head].x1;
           queue[rear].y1:=queue[head].y1;
           queue[rear].x2:=x;
           queue[rear].y2:=y;
           queue[rear].pre:=form[queue[head].x2,queue[head].y2];
           queue[rear].now:=form;
           queue[rear].step:=queue[head].step+1;
           inc(sum);
           can[sum]:=form;
          end;
       end;
    end;
   inc(head);
  end;
end;
begin
 head:=1;
 rear:=1;
 flag:=true;
 for i:=1 to 4 do
  begin
   for j:=1 to 4 do
    begin
     read(ch);
     case ch of
    'B':begin
         queue[1].now[i,j]:=1;
         can[1,i,j]:=1;
        end;
    'W':begin
         queue[1].now[i,j]:=2;
         can[1,i,j]:=2;
        end;
    'O':begin
         queue[1].now[i,j]:=0;
         can[1,i,j]:=0;
         if flag
          then
           begin
            queue[1].x1:=i;
            queue[1].y1:=j;
            flag:=false;
           end
          else
           begin
            queue[1].x2:=i;
            queue[1].y2:=j;
           end;
         queue[1].step:=0;
        end;
     end;
    end;
   readln;
  end;
 queue[1].pre:=-1;
 sum:=1;
 bfs;
end.

测试结果

测试通过 Accepted

总耗时: 4 ms
0 / 0 数据通过测试.
运行结果
测试点#chess.in 结果:AC 内存使用量: 256kB 时间使用量: 1ms
测试点#chess1.in 结果:AC 内存使用量: 256kB 时间使用量: 0ms
测试点#chess10.in 结果:AC 内存使用量: 256kB 时间使用量: 0ms
测试点#chess2.in 结果:AC 内存使用量: 256kB 时间使用量: 1ms
测试点#chess3.in 结果:AC 内存使用量: 256kB 时间使用量: 0ms
测试点#chess4.in 结果:AC 内存使用量: 256kB 时间使用量: 0ms
测试点#chess5.in 结果:AC 内存使用量: 256kB 时间使用量: 0ms
测试点#chess6.in 结果:AC 内存使用量: 256kB 时间使用量: 0ms
测试点#chess7.in 结果:AC 内存使用量: 256kB 时间使用量: 0ms
测试点#chess8.in 结果:AC 内存使用量: 256kB 时间使用量: 1ms
测试点#chess9.in 结果:AC 内存使用量: 256kB 时间使用量: 1ms

missing U

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值