有了上次题目看错的教训后再不敢随便看题了usaco太坑,这题绝对不水,传送门还特别玄学自然代码短不了…
代码:
const z:array[1..4,1..2]of -1..1=((1,0),(0,1),(-1,0),(0,-1));
var i,j,k:longint;
m,n:longint;
pdx,pdy:longint;
csmx,csmy:array['A'..'Z',0..1]of longint;
a,boo:array[-1..1000,-1..1000]of boolean;
b:array[-1..1000,0..1000]of longint;
h,t:longint;
ch:char;
fx,fy,lx,ly:longint;
x,y,u,p:array[0..4000000]of longint;//开大一点
begin
readln(m,n);
for i:=1 to m do
begin
for j:=1 to n do
begin
read(ch);
if ch='@' then
begin
fx:=i;
fy:=j;
a[i,j]:=false;
end;
if ch='=' then
begin
lx:=i;
ly:=j;
a[i,j]:=true;
end;
if ch='#' then
begin
a[i,j]:=false;
end;
if ch='.' then
begin
a[i,j]:=true;
end;
if ch in ['A'..'Z'] then//判断传送门
begin
a[i,j]:=true;
if csmx[ch,0]<>0 then//如果还没有找到同字母的传送门
begin
csmx[ch,1]:=i;
csmy[ch,1]:=j;
b[i,j]:=ord(ch)*10;
end
else//找到过了
begin
csmx[ch,0]:=i;
csmy[ch,0]:=j;
b[i,j]:=ord(ch)*10+1;
end;
end
else
b[i,j]:=0;
end;
readln;
end;
h:=1;
t:=1;
u[1]:=0;
x[1]:=fx;
y[1]:=fy;
repeat
if (x[t]=lx) and (y[t]=ly) then
begin
writeln(u[t]);
exit;
end;
if (b[x[t],y[t]]<>0) and (p[t]=0) then//因为有传送门必须走,所以直接修改尾巴上的值
if (a[csmx[chr(b[x[t],y[t]] div 10),b[x[t],y[t]] mod 10],
csmy[chr(b[x[t],y[t]] div 10),b[x[t],y[t]] mod 10]]) then//感觉有点眼酸...
begin
pdx:=csmx[chr(b[x[t],y[t]] div 10),b[x[t],y[t]] mod 10];//记录
pdy:=csmy[chr(b[x[t],y[t]] div 10),b[x[t],y[t]] mod 10];
x[t]:=pdx;
y[t]:=pdy;
p[t]:=1;
end;
if (b[x[t],y[t]]=0) or (p[t]=1) then//接下来就很简单了
for i:=1 to 4 do
if a[x[t]+z[i,1],y[t]+z[i,2]] then
begin
inc(h);
x[h]:=x[t]+z[i,1];
y[h]:=y[t]+z[i,2];
p[h]:=0;
u[h]:=u[t]+1;
if b[x[h],y[h]]=0 then//有传送门不可以赋为false,因为可能这只是一个中转站
a[x[h],y[h]]:=false;
end;
inc(t);
until t>h;
end.
如果不理解
有传送门不可以赋为false,因为可能这只是一个中转站
则举一个例子
###=###
#.....#
###A###
#.....#
#@#####
###a..#
#######
a,A一对传送门。
要先进入A从a出来,再进人a从A出来,不然不可以到终点,a就是一个中转站。
- 这可能才是本题考点。