死亡洞穴(Tyvj1575)

本文介绍了一种使用二分答案优化BFS算法解决迷宫问题的方法,通过将问题转换为二分查找,提高了算法的效率。文章详细解释了算法的实现过程,并提供了实际代码示例。

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

算法:二分答案

清北学堂的一道模拟赛题目,先算出每个能走的点距离最近的十字的距离,这里让所有的十字入队,然后BFS一次就可求出结果,一开始我是一个一个入队找的,结果超时了3个点。

然后就二分那个最小步数,从起点BFS到终点,如果能到终点,我们希望最小步数越大越好,所以向右找,如果不能到或者是起点就比最小步数要小,那么就找一个更小的,向左找。


program P1575;

const
 maxn=500;
 max1=250000;
 dx:array [1..4] of -1..1=(0,-1,0,1);
 dy:array [1..4] of -1..1=(-1,0,1,0);

type
 atp=record
  x,y:longint;
 end;

var
 n,m,sx,sy,ex,ey,tot,head,tail,max:longint;
 b,bb:array [0..maxn,0..maxn] of boolean;
 d:array [0..maxn,0..maxn] of longint;
 cross,que:array [0..max1] of atp;

procedure init;
var
 i,j:longint;
 ch:char;
begin
 fillchar(d,sizeof(d),100);
 readln(n,m);
 for i:=1 to n do
  begin
   for j:=1 to m do
    begin
     read(ch);
     if ch='V' then
      begin
       b[i,j]:=true;
       sx:=i;
       sy:=j;
      end;
     if ch='J' then
      begin
       b[i,j]:=true;
       ex:=i;
       ey:=j;
      end;
     if ch='+' then
      begin
       b[i,j]:=false;
       inc(tot);
       cross[tot].x:=i;
       cross[tot].y:=j;
      end;
     if ch='.' then b[i,j]:=true;
    end;
   readln;
  end;
end;

function min(x,y:longint):longint;
begin
 if x<y then exit(x) else exit(y);
end;

procedure cl;
var
 i,tx,ty,dep:longint;
begin
 fillchar(bb,sizeof(bb),false);
 for i:=1 to tot do
  begin
   inc(tail);
   que[i].x:=cross[i].x;
   que[i].y:=cross[i].y;
   d[cross[i].x,cross[i].y]:=0;
  end;
 head:=0;
 while head<tail do
  begin
   inc(head);
   for i:=1 to 4 do
    begin
     tx:=que[head].x+dx[i];
     ty:=que[head].y+dy[i];
     if (b[tx,ty]) and (not bb[tx,ty]) then
      begin
       inc(tail);
       bb[tx,ty]:=true;
       que[tail].x:=tx;
       que[tail].y:=ty;
       d[tx,ty]:=min(d[tx,ty],d[que[head].x,que[head].y]+1);
       if d[tx,ty]>max then max:=d[tx,ty];
      end;
    end;
  end;
end;

function get(x:longint):boolean;
var
 i,tx,ty:longint;
begin
 fillchar(bb,sizeof(bb),false);
 head:=0;
 tail:=1;
 que[1].x:=sx;
 que[1].y:=sy;
 if d[sx,sy]<x then exit(true);
 bb[sx,sy]:=true;
 while head<tail do
  begin
   inc(head);
   for i:=1 to 4 do
    begin
     tx:=que[head].x+dx[i];
     ty:=que[head].y+dy[i];
     if (b[tx,ty]) and (not bb[tx,ty]) and (d[tx,ty]>=x) then
      begin
       if (tx=ex) and (ty=ey) then exit(false);
       bb[tx,ty]:=true;
       inc(tail);
       que[tail].x:=tx;
       que[tail].y:=ty;
      end;
    end;
  end;
 exit(true);
end;

procedure main;
var
 l,r,mid,ans:longint;
begin
 ans:=0;
 l:=0;
 r:=max;
 while l<r do
  begin
   mid:=(l+r) shr 1;
   if get(mid) then r:=mid
   else
    begin
     ans:=mid;
     l:=mid+1;
    end;
  end;
 writeln(ans);
end;

begin
 assign(input,'P1575.in'); reset(input);
 assign(output,'P1575.out'); rewrite(output);

 init;
 cl;
 main;

 close(input); close(output);
end.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值