赞
踩
跳马问题也称为骑士周游问题,是算法设计中的经典问题。其一般的问题描述是:
考虑国际象棋棋盘上某个位置的一只马,它是否可能只走63步,正好走过除起点外的其他63个位置各一次?如果有一种这样的走法,则称所走的这条路线为一条马的周游路线。试设计一个算法找出这样一条马的周游路线。
此题实际上是一个汉密尔顿通路问题,可以描述为:
在一个8×8的方格棋盘中,按照国际象棋中马的行走规则从棋盘上的某一方格出发,开始在棋盘上周游,如果能不重复地走遍棋盘上的每一个方格,
这样的一条周游路线在数学上被称为国际象棋盘上马的哈密尔顿链。请你设计一个程序,从键盘输入一个起始方格的坐标,由计算机自动寻找并打印
出国际象棋盘上马的哈密尔顿链。
能够想到的思路是用回溯,马在每一个点最多有8种跳法,遍历所有这8种可能的跳法即可得到结果。这是回溯算法中的子集树的类型,与典型的子集树问题类型不同的是,这里每一枝有8种可能的选择,而典型的子集树问题只有0,1两种选择。
下面是该算法的实现:
上述简单回溯算法的时间复杂度是O(8^(N * N)),因为每次都按照Jump定义的顺序遍历,因此在算某些点的时候会很慢。
可以考虑采用启发式的遍历规则:即向前看两步,当每准备跳一步时,设准备跳到(x, y)点,计算(x, y)这一点可能往几个方向跳(即向前看两步),将这个数目设为(x, y)点的权值,将所 有可能的(x, y)按权值排序,从最小的开始,循环遍历所有可能的(x, y),回溯求出结果。算法可以求出所有可能的马跳棋盘路径,算出一个可行 的结果很快,但在要算出所有可能结果时,仍然很慢,因为时间复杂度本质上并没有改变,仍为O(8^(N * N))。下面是实现这一思想的代码:
另外,在查阅和搜索骑士问题的资料时,看到很多朋友说可以使用贪心算法,现在做一个验证看贪心法到底对不对:在只需要一个可行结果时,用贪心算法来替代回溯算法,对KnightTravel2稍做一下修改,在每次选择下一步时都贪心的选择权值最小的那一步,这样就省去了回溯的递归,算法复杂度为O(N * N)的线性时间。代码如下:
但很遗憾,实验证明贪心法并不是正确的,因为不能证明贪心选择一定会得到问题的解。可以举出反例:当马开始在(5, 3)位置时,使用贪心算法得不到可行路径,但使用改进后的回溯算法KnightTravel2,则可以解出结果。
综上所述,骑士周游问题不能使用贪心法求解。改进后的回溯法是一个可行的方案,但时间复杂度仍然很高。在王晓东的《计算机算法设计与分析》一书上看到该问题可以用分治递归法求解,但一直没有想出答案,网上也很难找到相关方面的资料。
【参考文献】
[1] 《计算机算法设计与分析(第2版)》 王晓东 电子工业出版社http://blog.csdn.net/eshow/article/details/1779307
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。