《Python科学计算》的作者
分类: Python/Ruby
2012-02-23 20:31:47
按照下面的规则,找到从开始方格(红色)到目标方格(绿色)的路径。
下图是一个例子,左图为迷宫,右图为解。从解可以看出,每一行所经过的方格数等于右侧对应的数字,而每一列所经过的方格数等于上方对应的数字。
下面是一个10×10的迷宫,这个题目有些难度,手工解决花了不少时间,让我们用Python写一个程序解解看。
解这种题目最简单的方法就是回溯法,回溯法最简单的实现就是用递归。这里先给出完整的程序,然后再简单介绍一下编程思路。
Maze类的maze属性是一个集合,用来记录当前走过的所有的方格的坐标。sx和sy属性分别用来记录每列以及每行走过的方格数。tx和ty属性保存每列和每行走过的目标方格数。add()和remove()方法用来添加和删除方块,在添加或删除方块的时候,需要同时更新sx和sy属性中相应坐标的值。
check()方法用来检测当前的状态是否符合规则。pos参数为最后一个添加的方格坐标,也就是需要检查的对象。我们先看看这个方格所在的行和列的对应的方格数是否满足条件,这个条件很容易理解:
由于入口在左上,而出口在右下,因此一旦某一行或者列的方格数等于了规则所给出的方格数,那么它左边的列或者上面的行就必须也符合规定的数目。因为如果要走回的话,那么就必须再经过一次已经当前方格所在的行和列,这样就不能满足条件了。这也就是说,当走到某个方格时,那行的方格数已经等于了指定的值时,我们就不能再走那行上方的方格了。列方向上也是同样的道理。这个条件很关键,它能够裁剪掉大量的后续选路径,如果去除掉这个条件检测,那么等几个小时可能都出不来结果。
solve()方法完成递归回溯求解,它找到从pos到target的路径:
❶首先调用add(pos)走上坐标为pos方格。❷然后判断当前的状态是否符合条件。如果符合,对于pos的所有邻近的未走过的方格递归调用solve()方法,直到找到目标为止。在solve()返回之前,❸需要通过remove()还原到刚进入此方法时的状态,这样才能够正常回溯到上层的调用。
程序的输出为: