应用举例跳马问题动画演示

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
如果我对马可以走到的四个点都编上号(方
向),那么我们很容易得到每一个方向上两 个坐标和原位置的关系。
同时,四个方向都有了编号,那么在选择路
径的时候也就可以不采用任选的方式了,只 需按照编号依次尝试就可以了。
跳马问题
4 3 2 1
若马所处的位置为 (x,y) , 则其下一步可以到达的四 个位置分别是(x+1, y-2), (x+2, y-1),(x+2, y+1), (x+1, y+2)。
跳马问题
骑士遍历问题的解空间是从左下角到右上角
的所有路径。
解空间的长度是所有路径中最长的路径的长
度。
解空间的组织形式是一棵四叉树,一个可行
的解就是从根节点到叶子节点的一条路径。 控制策略则是马必须在棋盘内。
跳马问题(递归)
procedure search(k: integer); // 递归查找 begin for i := 1 to 4 do // 依次尝试四个方向 if (x + dx[i] <= n) and (y + dy[i] > 0) and (y + dy[i] <= n) then // 在棋盘上 begin route[k] := i; // 记录下当前方向 x := x + dx[i]; y := y + dy[i]; // 修改扩展节点坐标 if (x = n) and (y = m) then // 是否是目标点 begin output(k); halt; // 是目标点,输出结果并终止程序 end else search(k+1); // 不是目标点,继续尝试下一步 // 扩展出的点是死点,回溯 x := x - dx[i]; y := y - dy[i]; // 恢复扩展节点坐标 end; end;
应用举例—跳马问题

在n×m棋盘上有一中国象棋中的马:
1. 马走日字; 2. 马只能往右走。

请你找出一条可行路径,使得马可以从棋盘 的左下角(1,1)走到右上角(n,m)。
跳马问题
输入:9 5
输出: (1,1)->(3,2)->(5,1)->(6,3)->(7,1)->(8,3)->(9,5)
B3
A2 A1 A B1 B2 C2 C1
D3
D2 E1 D1
跳马问题
5. 从C2出发,有四条路径可以选择,选择D4,
从D4出发又有两条路径,选择E1错误,返 回D4选择E2,从E2出发有两条路径,先 选择F1错误,返回E2选择B,而B恰好是 我们要到达的目标点,至此,一条路径查找 成功。
B3 A2 A1 A B1 B2 C2 E2本例中,我们只要求输出一条可行路径,
如果我们需要输出所有的可行路径,怎样改 动此程序呢? 2. 如果我们把问题改成“在n×m的棋盘上有 一骑士,开始时,骑士在点(x,y),现在请你 找出一条可行的路径,使得骑士可以不重复 的走遍棋盘上的每一个点。”的话,又要如 何编写此程序呢?
跳马问题
马走日字,当马一开始在黄点时,它下一步
可以到达的点有以下的八个,但由于题目规 定了只能往右走的限制,所以它只能走到四 个绿色点之一。
跳马问题
1. 当马一开始位于左下角的时候,根据规则,
它只有两条线路可以选择(另外两条超出棋 盘的范围),我们无法预知该走哪条,故任 意选择一条,到达A1。
A2 A1 A
跳马问题
2. 当到达A1点后,又有三条线路可以选择,
于是再任意选择一条,到达B1。 3. 从B1再出发,又有两条线路可以选择,先 选一条,到达C1。
B3 A2 A1 B1 A B2 C2 C1
跳马问题
4. 从C1出发,可以有三条路径,选择D1。但到了
D1以后,我们无路可走且D1也不是最终目标点, 因此,选择D1是错误的,我们退回C1重新选择 D2。同样D2也是错误的。再回到C1选择D3。 D3只可以到E1,但E1也是错误的。返回D3后, 没有其他选择,说明D3也是错误的,再回到C1。 此时C1不再有其他选择,故C1也是错误的,退回 B1,选择C2进行尝试。
在使用增量数组后,只要 知道方向t,下一步的位置 就是(x+dx[t], y+dy[t])。
增量数组: dx = (1, 2, 2, 1) dy = (-2, -1, 1, 2)
跳马问题
为了判断棋子是否落在棋盘上,我们还必须
知道当前棋子(扩展节点)的位置信息。而 用一系列的方向来表示就比较麻烦,因此, 我们另外使用两个变量来保存当前棋子的坐 标。但这时千万要注意的是一定要在回溯的 时候,修改当前棋子的坐标。
跳马问题(非递归)
top := 1; // 从第一步开始尝试 while ((x <> n) or (y <> m)) and (top > 0) do begin inc(route[top]); // 取下一个方向为当前方向 if (route[top] > 4) then begin // 是否四个方向全部尝试过 dec(top); // 都尝试过,回溯,并恢复扩展节点坐标 x := x - dx[route[top]]; y := y - dy[route[top]]; end else begin // 还有方向可以尝试 x := x + dx[route[top]]; y := y + dy[route[top]]; // 修改扩展节点坐标 if (x > n) or (y > m) or (y < 1) then begin // 活动点是否在棋盘上 x := x - dx[route[top]]; y := y - dy[route[top]]; // 不在棋盘上,恢复 end else begin // 在棋盘上 inc(top); // 继续尝试一步 route[top] := 0; // 下一步从第一个方向开始尝试 end; end; end;
D4
F1
跳马问题

从上面的分析我们可以得知:
1. 在无法确定走哪条线路的时候,任选一条线路 进行尝试;
2. 当从某点出发,所有可能到达的点都不能到达 终点时,说明此点是一个死节点,必须回溯到 上一个点,并重新选择一条新的线路进行尝试。
跳马问题
为了描述路径,我们最直接的方法就是记录
路径上所有点的坐标。但比较繁琐。
相关文档
最新文档