再探跳马问题(骑士周游问题)

2007年09月11日 17:57:00

 买回了王晓东的《算法设计与分析习题解答》,书中代码是用Java写的,看了跳马问题的部分,基本理解了算法。首先说明一下,《算法设计与分析》原书的题目其实是要找一条哈密尔顿通路,而《习题解答》中是解哈密尔顿回路的,即不仅要不重复的跳过棋盘的每一个格子,最后还要能回到出发点。先解释一下寻找哈密尔顿回路的算法:

【问题描述】

对于给定的m × n的国际象棋棋盘,mn均为大于5的偶数,且|m - n| <= 2,试设计一个分治算法找出一条马的哈密尔顿回路。

【算法】

首先,考虑n × n的棋盘,马踏棋盘是黑白相间的,对于一条哈密尔顿回路来说,马在棋盘上所踏过的黑色格子和白色格子相等,因此,棋盘的格子数应为偶数,n不能为奇数。即n为奇数的n × n棋盘不存在哈密尔顿回路(但可能存在哈密尔顿通路)。而对于m × n的棋盘(m != n),m, n均为奇数则不存在哈密尔顿回路。好在题目已经限定m, n均为偶数且|m - n| <= 2,这说明在这种情况下一定存在哈密尔顿回路。而在其他情况下,如m, n一奇一偶或|m - n| > 2是否存在哈密尔顿回路则不好说。至于题目为何要做此限定,如何证明这种限定的合理性则有待探究,当然对此问题的讨论也超过了本文的范围。

现在回到题目本身,算法考察一类具有特殊结构的解,这类解在棋盘的4个角都包含2条特殊边,如下图。称具有这类特殊结构的哈密尔顿回路为结构化的哈密尔顿回路。

用回溯法可在O(1)(留有疑问)时间内找出6 × 6, 6 × 8, 8 × 8, 8 × 10, 10 × 10, 10 × 12棋盘上的结构化的哈密尔顿回路。同时注意到四个角上每个点只有两条边,而哈密尔顿回路要经过这个角,走的边不能重复,因此这两条边必然在汉密尔顿回路的路径上。故结构化的解一定形如下图:

而对于6 × 8, 8 × 10, 10 × 12的棋盘,旋转90度即可得到8 × 6, 10 × 8, 12 × 10的棋盘上结构化的哈密尔顿回路。

对于m, n >= 12的情形,采用分治策略。

1. 分治:将棋盘尽可能的平均分割成4块,当m, n = 4k时,分割为22k;当m, n = 4k + 2时,分割为12k12k + 2

2. 合并:4个子棋盘拼接后如下图:

分别删除4个子棋盘中的结构化的边A, B, C, D,添入新的边E, F, G, H,构成整个棋盘结构化的哈密尔顿回路,如下图所示:

                

从图中可以看出, 合并的过程其实很简单,如果把A, D, C, B看作风扇的桨叶,则合并后就是将桨叶依次逆时针向下打了一个点(逆时针旋转)。

至此,算法结束,我们可以看到,当n >= 12是使用分治法,分成4个子棋盘,而合并过程只需常数时间即可完成,设该算法时间为T(n),则有递推方程:T(n) = 4T(n / 2) + O(1),据Master定理知T(n) = O(n ^ 2),这就是在棋盘中寻找哈密尔顿回路的时间复杂度。比《跳马问题(骑士周游问题)初探 》一文中从给定起始点寻找哈密尔顿通路的问题快了不少。

【分析】

回到《算法分析与设计》一书中课后的那道题,是否存在一个分治的求哈密尔顿通路的算法呢?这个问题我现在还没有确切的答案,因为从网上搜索的一些资料看(CSDN的帖子中很多人问了这个问题),有几个网友说有一篇论文似乎是论述了类似的问题,分治的方法十分复杂,要根据不同的情况去分割问题,但很遗憾,这些网友们给出的论文地址已经无效,我没有看到确切的方法。

但如果想用类似解哈密尔顿回路的算法来解决哈密尔顿通路的问题,我分析认为不可能(即要分治不可能是像解回路一样分治,如前所说,答案可能在那篇神秘的论文中)。这种不可能正是由于“回路”和“通路”这一字之差引起的: 回路与起始点无关,算法只需在棋盘中能够找到一条哈密尔顿回路,则从任何一点都能不重复的经过棋盘上每一点并回到起始点。而哈密尔顿通路与起始点有关,且路径不是封闭的,这就使得回路中考察的结构化路径的解可能不存在,考虑起始点在最左上角的情形,通路不用再回到这个左上角,所以角上的两条边只用一条,这样在合并时通路问题就不会出现结构化路径中的中心对称结构。 因此,我们不能从回路算法中得到启发去找到通路问题的分治解。

当然,由于通路是比回路弱的一个解要求,当棋盘满足m, n为偶数,m, n >= 6且|m - n| <= 2的条件时,我们可以直接调用这个回路算法得到一条哈密尔顿回路,然后删去起始点和终点的边即得通路的解,而在不满足这个条件时,如5 × 5的棋盘上,对某些起始点是存在哈密尔顿通路的,仍然需要使用回溯的算法去求解,时间复杂度为O(8 ^ (m * n))。

从回溯算法的时间复杂度,又引出前面书中所说:“用回溯法可在O(1)时间内找出6 × 6, 6 × 8, 8 × 8, 8 × 10, 10 × 10, 10 × 12棋盘上的结构化的哈密尔顿回路。”的疑问,回溯法怎么可能是在O(1)时间内得到这些棋盘上回路的解呢?如果这样,就要求在这些规模的棋盘上构建议一条结构化的回路(即四角对称的回路)有固定的跳马方法,这种方法使得每一步跳马时的步子只有唯一选择,但即使这样也至少是个线性时间的复杂度啊。从书中的源代码看,好像是直接一一的读取这些规模棋盘上的回路(即回路已经手工构造好了),这样复杂度才是O(1),所以书中的这句话应该有错。

另外需要说明的是书的所附光盘并没有源代码,只有几个testcase,十分的遗憾(不知为什么不放,可能是怕盗版,大家拿到源码后都不买书了吧:),不过这一点比之国外教材就差了)。而书中的源代码中ReadStreamJava API中并不存在,kyeboard.readInt()也不知是从哪读的数据(光盘上也没有),反正代码中是用这个类来初始化6 × 6, 6 × 8, 8 × 8, 8 × 10, 10 × 10, 10 × 12这些特殊规模棋盘的解的。这种缺憾使得源码不能上机跑起来,我也没有手工的跑这个程序去分析(有时间再说吧),另外书中的代码的注释实在是太少了。这些遗憾都使得该书对读者来说不太方便。

【参考文献】

[1] 《计算机算法设计与分析(第2版)》 王晓东 电子工业出版社

[2] 《算法设计与分析习题解答》 王晓东 清华大学出版社

 
 

骑士周游问题(暴力解决:回溯法)

建议测试数据 3 0 或 4 0
  • H992109898
  • H992109898
  • 2016年02月16日 13:35
  • 1833

BFS 中国象棋中的跳马问题 (棋盘障碍)

题目描述 现在棋盘的大小不一定,由p,q给出,并且在棋盘中将出现障碍物(限制马的行动,与象棋走法相同) 输入 第一行输入n表示有n组测试数据。 每组测试数据第一行输入2个整数p...
  • deepseazbw
  • deepseazbw
  • 2017年07月17日 23:20
  • 305

跳马问题(骑士周游问题)初探

跳马问题也称为骑士周游问题,是算法设计中的经典问题。其一般的问题描述是:考虑国际象棋棋盘上某个位置的一只马,它是否可能只走63步,正好走过除起点外的其他63个位置各一次?如果有一种这样的走法,则称所走...
  • eshow
  • eshow
  • 2007年09月10日 16:00
  • 11293

骑士周游问题(贪心算法)的实现

  • 2012年03月22日 10:11
  • 56KB
  • 下载

骑士周游问题(暴力解决:回溯法)

建议测试数据 3 0 或 4 0
  • H992109898
  • H992109898
  • 2016年02月16日 13:35
  • 1833

数据结构与算法10:马踏棋盘问题(骑士周游问题)

问题描述:在一个国际象棋的棋盘上,一个马按照它的规则如何才能从一个点出发遍历每一个位置,且每个点只访问一次。     问题分析:这是一个深搜的问题,沿着一条路前进直到遍历全部的点,那就完成了...
  • jarelzhou
  • jarelzhou
  • 2014年01月20日 16:36
  • 1280

骑士周游问题

#include "stdafx.h"#include #include using namespace std;const int N = 5;int array[N][N];struct No...
  • newish21
  • newish21
  • 2007年10月24日 13:37
  • 495

马踏棋盘算法(骑士周游问题)

将马随机放在国际象棋的8×8棋盘的某个方格中,马按走棋规则进行移动。要求每个方格只进入一次,走遍棋盘上全部64个方格。 代码: #include "stdafx.h" #include #inc...
  • u011643312
  • u011643312
  • 2017年01月31日 15:46
  • 803

马踏棋盘算法 [骑士周游问题] --->图

马塔棋盘算法又称骑士周游或骑士漫游问题是算法设计的经典问题之一。 国际象棋的棋盘为8*8的方格棋盘,现将“马”放在任意指定的方格中,按照“马”走棋的规则将“马”进行移动,要求每个方格只能进入一次,最终...
  • luobo140716
  • luobo140716
  • 2016年06月30日 22:33
  • 1166

马踏棋盘算法(骑士周游问题)

一、马踏棋盘算法 1、国际象棋的棋盘为8*8的方格棋盘,将“马”放在任意指定的方格中,按照“马”走棋的规则将“马”进行移动。要求每个方格只能进入一次,最终使得“马”走遍棋盘64个方格。 2、关于国际象...
  • cdu09
  • cdu09
  • 2014年03月03日 21:38
  • 3362
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:再探跳马问题(骑士周游问题)
举报原因:
原因补充:

(最多只允许输入30个字)