| ||||||||||
| Online Judge | Problem Set | Authors | Online Contests | User | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest | |||||||||
推箱子Pascal源程序 简单AC优先队列的方法(pascal):
var
dx:array[1..4] of longint=(-1,1,0,0);
dy:array[1..4] of longint=(0,0,1,-1);
p1:array[1..4] of char=('n','s','e','w');
p2:array[1..4] of char=('N','S','E','W');
type
rec=record
f:ansistring;
x,y,bx,by,step,step2:longint;
end;
var
map:array[1..20,1..20] of boolean;
ch:char;
stx,sty,enx,eny,bx,by,n,m,r,cash:longint;
q:array[1..10000] of rec;
v:array[1..20,1..20,1..20,1..20] of boolean;
procedure swap(var x,y:rec);
var
t:rec;
begin
t:=x;x:=y;y:=t;
end;
procedure change(i:longint);
var
lc,rc,min:longint;
begin
min:=i;lc:=i shl 1;rc:=lc+1;
if (lc<=r) and ((q[lc].step<q[min].step) or ((q[lc].step=q[min].step) and (q[lc].step2<q[min].step2))) then min:=lc;
if (rc<=r) and ((q[rc].step<q[min].step) or ((q[rc].step=q[min].step) and (q[rc].step2<q[min].step2))) then min:=rc;
if i<>min then
begin
swap(q[i],q[min]);
change(min);
end;
end;
function getmin:rec;
begin
getmin:=q[1];q[1]:=q[r];dec(r);change(1);
end;
procedure insert(x:rec);
var
i:longint;
begin
inc(r);
q[r]:=x;i:=r;
while (i>1) and ((q[i shr 1].step>q[i].step) or ((q[i shr 1].step=q[i].step) and (q[i shr 1].step2>q[i].step2))) do
begin
swap(q[i],q[i shr 1]);
i:=i shr 1;
end;
end;
procedure init;
var i,j:longint;
begin
fillchar(map,sizeof(map),true);
for i:=1 to n do
begin
for j:=1 to m do
begin
read(ch);
if ch='#' then map[i,j]:=false
else if ch='S' then
begin
stx:=i;sty:=j;
end
else if ch='T' then
begin
enx:=i;eny:=j;
end
else if ch='B' then
begin
bx:=i;by:=j;
end;
end;
readln;
end;
end;
function ok(x,y:longint):boolean;
begin
if (x<1) or (x>n) or (y<1) or (y>m) then exit(false);
exit(map[x,y]);
end;
procedure bfs;
var
i:longint;
x,nx:rec;
begin
fillchar(v,sizeof(v),false);
x.f:='';x.step:=0;x.step2:=0;
x.x:=stx;x.y:=sty;x.bx:=bx;x.by:=by;
r:=0;
insert(x);
while r>0 do
begin
x:=getmin;
if (x.bx=enx) and (x.by=eny) then
begin
writeln(x.f);
exit;
end;
for i:=1 to 4 do
begin
if (x.x+dx[i]=x.bx) and (x.y+dy[i]=x.by) and ok(x.bx+dx[i],x.by+dy[i]) then
begin
nx:=x;
nx.bx:=x.bx+dx[i];nx.by:=x.by+dy[i];
nx.x:=x.x+dx[i];nx.y:=x.y+dy[i];
nx.step:=x.step+1;
nx.step2:=x.step2+1;
nx.f:=x.f+p2[i];
if not v[nx.x,nx.y,nx.bx,nx.by] then
begin
insert(nx);
v[nx.x,nx.y,nx.bx,nx.by]:=true;
end;
end
else if ok(x.x+dx[i],x.y+dy[i]) and (not ((x.x+dx[i]=x.bx) and (x.y+dy[i]=x.by))) then
begin
nx:=x;
nx.x:=x.x+dx[i];nx.y:=x.y+dy[i];
nx.f:=x.f+p1[i];
nx.step2:=x.step2+1;
if not v[nx.x,nx.y,nx.bx,nx.by] then
begin
insert(nx);
v[nx.x,nx.y,nx.bx,nx.by]:=true;
end;
end;
end;
end;
writeln('Impossible.');
end;
begin
cash:=0;
while not eof do
begin
readln(n,m);
if n+m=0 then break;
init;
inc(cash);
writeln('Maze #',cash);
bfs;
writeln;
end;
writeln;
end.
双向BFS的方法也许更好理解:
const
dx:array[1..4] of longint=(-1,1,0,0);dy:array[1..4] of longint=(0,0,1,-1);
p:string[4]=('NSEW'); m:string[4]=('nsew');
type
node=record
x,y:longint; ans:ansistring;
end;
rec=record
bx,by,px,py:longint; ans:ansistring;
end;
var
r,c,begx,begy,endx,endy,begsx,begsy,cases,i,j:longint;
map:array[1..21] of string[20];
vis,v:array[1..21,1..21] of boolean;
f1,g1:node; f,g:rec;
q:array[1..401] of rec;
q1:array[1..401] of node;
function ok(x,y:longint):boolean;
begin
if (x>=1) and (x<=r) and (y>=1) and (y<=c) then exit(true) else exit(false);
end;
function slove(bx,by,ex,ey:longint):boolean;
var l,r,i:longint;
begin
fillchar(v,sizeof(v),false); v[bx,by]:=true;
f1.x:=bx; f1.y:=by; f1.ans:='';
if (bx=ex) and (by=ey) then exit(true);
l:=0; r:=1; q1[r]:=f1;
while l<r do
begin
inc(l); f1:=q1[l];
for i:=1 to 4 do
begin
g1.x:=f1.x+dx[i]; g1.y:=f1.y+dy[i];
if not ok(g1.x,g1.y) or (map[g1.x,g1.y]='#') or ((f.bx=g1.x) and (f.by=g1.y)) then continue;
if not v[g1.x,g1.y] then
begin
v[g1.x,g1.y]:=true; g1.ans:=f1.ans+m[i];
if (g1.x=ex) and (g1.y=ey) then
begin
f1:=g1; exit(true);
end;
inc(r); q1[r]:=g1;
end;
end;
end;
exit(false);
end;
function bfs():boolean;
var l,r,newx,newy,tx,ty:longint;
begin
f.bx:=begx; f.by:=begy; f.px:=begsx; f.py:=begsy; f.ans:='';
vis[begx,begy]:=true; r:=1; l:=0; q[r]:=f;
while l<r do
begin
inc(l); f:=q[l];
for i:=1 to 4 do
begin
newx:=f.bx+dx[i]; newy:=f.by+dy[i];
tx:=f.bx-dx[i]; ty:=f.by-dy[i];
if (not ok(newx, newy)) or (map[newx,newy]='#') or (not ok(tx,ty))
or (map[tx,ty]='#') or (vis[newx,newy]) then continue;
if slove(f.px,f.py,tx,ty) then
begin
g.bx:=newx; g.by:=newy; g.px:=f.bx; g.py:=f.by;
g.ans:=f.ans+f1.ans+p[i];
if (g.bx=endx) and (g.by=endy) then exit(true);
vis[newx,newy]:=true; inc(r); q[r]:=g;
end;
end;
end;
exit(false);
end;
begin
cases:=1; readln(r,c);
while (r+c>0) do
begin
fillchar(vis,sizeof(vis),0);
writeln('Maze #', cases); inc(cases);
for i:=1 to r do readln(map[i]);
for i:=1 to r do
for j:=1 to c do
begin
if map[i,j]='B' then
begin begx:=i; begy:=j; end;
if map[i,j]='T' then
begin endx:=i; endy:=j; end;
if map[i,j]='S' then
begin begsx:=i; begsy:=j; end;
end;
if bfs() then writeln(g.ans) else writeln('Impossible.');
readln(r,c); writeln;
end;
end.
Followed by:
Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator