算法:二分答案
清北学堂的一道模拟赛题目,先算出每个能走的点距离最近的十字的距离,这里让所有的十字入队,然后BFS一次就可求出结果,一开始我是一个一个入队找的,结果超时了3个点。
清北学堂的一道模拟赛题目,先算出每个能走的点距离最近的十字的距离,这里让所有的十字入队,然后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.