主题:[讨论]我的跳马格,大家PP
[问题描述]
设有一个n*m的棋盘(2<=n<=50,2<=m<=50),找出从左下到右上的最短路径步数和路径。马走的规则为:1、马走日字;2、马只能向右走。
[输入样例]
4 4
[输出样例]
3
(1,1)->(2,3)->(4,4)
我用Delphi写的,不足之处请大家指出~~~~~~~~~
代码如下:
program tiaoma2;
{$APPTYPE CONSOLE}
const
fi:array[1..4]of integer=(1,2,2,1);
fj:array[1..4]of integer=(2,1,-1,-2); {方向矢量}
type
stp=record {位置}
x,y:integer;
end;
steps=record
len:integer; {步数}
sp:array[1..1000]of stp; {每步位置}
end;
var
n,m:integer;
step:array[0..9999]of steps; {搜索使用的队列}
used:array[1..50,1..50]of boolean; {记录访问过的点}
procedure print(d,k:integer); {输出过程}
var i:integer;
begin
writeln(k); write('(1,1)');
with step[d] do
for i:=2 to k do
with sp[i] do
write('->(',x,',',y,')');
readln;
halt {退出程序}
end; {Endprint}
procedure bfs; {广搜过程}
var s,e,i,ti,tj,sx,sy:integer;
begin
with step[0] do
begin sp[1].x:=1; sp[1].y:=1; len:=1 end;
fillchar(used,sizeof(used),0); s:=0; e:=1; used[1,1]:=true; {初始化}
repeat {广搜循环}
with step[s] do
with sp[len] do
begin
sy:=y; {记录上一步的坐标(为了省去反复读内存的时间)}
sx:=x
end; {Endwith}
if(sx=n)and(sy=m)then print(s,step[s].len); {如果已跳到,那么输出}
for i:=1 to 4 do {搜索所有可能}
begin
ti:=sx+fi[i]; tj:=sy+fj[i]; {临时新坐标}
if(ti in[1..n])and(tj in[1..m]) {如果临时坐标在范围内,且未访问}
and(not used[ti,tj])then
begin
used[ti,tj]:=true; {不再访问该坐标}
step[e]:=step[s]; {在原来基础上操作(为了省去反复读内存的时间)}
with step[e]do
begin
inc(len); {步数累加}
with sp[len]do
begin
x:=ti; {记录新坐标}
y:=tj
end {Endwith}
end; {Endwith}
e:=(e+1)mod 10000 {要访问的结点入队}
end {Endif}
end; {Endfor}
s:=(s+1)mod 10000 {访问过的结点出队}
until s=e {如果所有可能都搜索过,且没找到(找到会自动跳出),结束搜索}
end; {EndBFS}
procedure no; {如果没有结果,才执行这个过程}
begin
writeln('Not found!');
readln
end; {Endno}
begin {Main}
readln(n,m);
bfs; {广度优先搜索}
no
end.
设有一个n*m的棋盘(2<=n<=50,2<=m<=50),找出从左下到右上的最短路径步数和路径。马走的规则为:1、马走日字;2、马只能向右走。
[输入样例]
4 4
[输出样例]
3
(1,1)->(2,3)->(4,4)
我用Delphi写的,不足之处请大家指出~~~~~~~~~
代码如下:
program tiaoma2;
{$APPTYPE CONSOLE}
const
fi:array[1..4]of integer=(1,2,2,1);
fj:array[1..4]of integer=(2,1,-1,-2); {方向矢量}
type
stp=record {位置}
x,y:integer;
end;
steps=record
len:integer; {步数}
sp:array[1..1000]of stp; {每步位置}
end;
var
n,m:integer;
step:array[0..9999]of steps; {搜索使用的队列}
used:array[1..50,1..50]of boolean; {记录访问过的点}
procedure print(d,k:integer); {输出过程}
var i:integer;
begin
writeln(k); write('(1,1)');
with step[d] do
for i:=2 to k do
with sp[i] do
write('->(',x,',',y,')');
readln;
halt {退出程序}
end; {Endprint}
procedure bfs; {广搜过程}
var s,e,i,ti,tj,sx,sy:integer;
begin
with step[0] do
begin sp[1].x:=1; sp[1].y:=1; len:=1 end;
fillchar(used,sizeof(used),0); s:=0; e:=1; used[1,1]:=true; {初始化}
repeat {广搜循环}
with step[s] do
with sp[len] do
begin
sy:=y; {记录上一步的坐标(为了省去反复读内存的时间)}
sx:=x
end; {Endwith}
if(sx=n)and(sy=m)then print(s,step[s].len); {如果已跳到,那么输出}
for i:=1 to 4 do {搜索所有可能}
begin
ti:=sx+fi[i]; tj:=sy+fj[i]; {临时新坐标}
if(ti in[1..n])and(tj in[1..m]) {如果临时坐标在范围内,且未访问}
and(not used[ti,tj])then
begin
used[ti,tj]:=true; {不再访问该坐标}
step[e]:=step[s]; {在原来基础上操作(为了省去反复读内存的时间)}
with step[e]do
begin
inc(len); {步数累加}
with sp[len]do
begin
x:=ti; {记录新坐标}
y:=tj
end {Endwith}
end; {Endwith}
e:=(e+1)mod 10000 {要访问的结点入队}
end {Endif}
end; {Endfor}
s:=(s+1)mod 10000 {访问过的结点出队}
until s=e {如果所有可能都搜索过,且没找到(找到会自动跳出),结束搜索}
end; {EndBFS}
procedure no; {如果没有结果,才执行这个过程}
begin
writeln('Not found!');
readln
end; {Endno}
begin {Main}
readln(n,m);
bfs; {广度优先搜索}
no
end.