【题5】骑士游历问题(1)
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
【题5】骑士游历问题(1)
设有一个n*m的棋盘(2≤n≤50,2≤m≤50),如图10.2.1。
在棋盘上任一点有一个中国象棋马,
图10.2.1
马走的规则为:
1.马走日字
2.马只能向右走。
即如图10.2.2所示:
图10.2.2
问题:当N,M 输入之后,找出一条从左下角到右上角的路径。
例如:输入N=4,M=4。
对应的路径如图10.2.3所示:
图10.2.3
输出:路径的格式:(1,1)->(2,3)->(4,4)
若不存在路径,则输出"no"
题解
1.计算跳马方向
按题意,中国象棋马共有四个跳动方向
图10.2.4
我们通过子程序move(x,y,x1,y1,i)计算中国象棋马从(x,y)出发,沿i方向跳至(x1,y1)的过程
procedure move(x,y:byte;var x1,y1:byte;i:integer);
begin
case i of {根据方向计算跳后位置}
1:begin x1←x-2;y1←y+1;end;
2:begin x1←x-1;y1←y+2;end;
3:begin x1←x+1;y1←y+2;end;
4:begin x1←x+2;y1←y+1;end;
end;{case}
end;{move}
2.从起始点出发,沿方向序列输出路径
设
var
path:array[1..1000] of integer;{path[i]—第i步的方向。
初始时path 清零}
由(1,1)至(n,m)的路径长度为k。
我们通过调用print(k)过程输出该条路径。
procedure print(k:integer);
var
x,y,x0,y0:byte;
i:integer;
begin
x←1; y←1;{从(1,1)出发}
write(’(’,x,’,’,y,’)’);
for i←1 to k do {顺序输出长度为k的跳动路线}
begin
move(x,y,x0,y0,path[i]);{第i步由(x,y)跳至(x0,y0)} write(’=>(’,x0,’,’,y0,’)’);
x←x0; y←y0; {从(x0,y0)继续往下跳}
end;{for}
writeln
end;{print}
3.回溯搜索
状态:起跳位置(x,y)和步数k,即准备从(x,y)出发跳第k步;
目标:(x,y)为目的地(n,m)。
若满足条件,则输出长度为k-1的路径并成功退出;
搜索范围:四个跳动方向,即1≤i≤4。
中国象棋马沿i方向跳至(x1,y1);
约束条件:(x1,y1)在界内。
若满足条件,则记下第k步的方向i,并从(x1,y1)出发递归第k+1步;
procedure search(k:integer;x,y:byte);
var
i:integer;
x1,y1:byte;
begin
if (x=n) and (y=m) {若(x,y)为目的地,则输出长度为k-1的路径并成功退出}
then begin
print(k-1); halt;
end;
for i←1 to 4 do {搜索4个方向}
begin
move(x,y,x1,y1,i); { 中国象棋马从(x,y)出发,沿i方向跳至(x1,y1)} if (x1 in [1..n]) and (y1 in [y+1..m]){若(x1,y1)在右方界内,则记下第k步的方向i,并从(x1,y1)出发递归第k+1步}
then begin path[k]←i; search(k+1,x1,y1);end;{then}
end{for}
end;{ search }
显然,递归调用search(1,1,1)后可得出由(1,1)至(n,m)的一条路径。