一个详细的实施
乍一看它看起来好像你必须区分在那里你可以从电流源直接移动到当前目标的情况下,以及那些必须分两步移动最大磁盘的磁盘。下面的实现确实是:
class Stack(object):
def __init__(self, index, name, disks):
self.index = index
self.name = name
self.disks = disks
def __str__(self):
return self.name
def __repr__(self):
return 'Stack(%r, %r, %r)' % (self.index, self.name, self.disks)
def is_adjacent(self, other):
return other.index in (self.index + 1, self.index - 1)
def push(self, disk):
assert len(self.disks) == 0 or self.disks[-1] > disk
self.disks.append(disk)
def pop(self):
return self.disks.pop()
class Hanoi(object):
def __init__(self, n):
source = Stack(0, "source", range(n, 0, -1))
helper = Stack(1, "helper", [])
target = Stack(2, "target", [])
self.stacks = [source, helper, target]
self.hanoi(n, source, target)
def hanoi(self, n, source, target):
"""Move n disks from source to target using remaining stack"""
helper = self.stacks[3 - source.index - target.index]
if n == 0:
return
if source.is_adjacent(target):
self.hanoi(n - 1, source, helper)
self.move(source, target)
self.hanoi(n - 1, helper, target)
else:
assert helper.is_adjacent(source) and helper.is_adjacent(target)
self.hanoi(n - 1, source, target)
self.move(source, helper)
self.hanoi(n - 1, target, source)
self.move(helper, target)
self.hanoi(n - 1, source, target)
def move(self, s, d):
assert s.is_adjacent(d)
disk = s.pop()
print "moving %d from %s to %s" % (disk, s, d)
d.push(disk)
Hanoi(5)
的Stack
对象有助于保持你的堆栈在一起的一个所有的东西:名称,位置,与邻居关系,磁盘的当前序列。如果添加了第三个元素来容纳该索引,则可以使用元组,但我认为OOP更直观。
Hanoi
类将一组堆栈连在一起。这允许hanoi
方法只指定源和目标,而推断第三个堆栈。你可以用不同的代码进行编码,但是我发现省略助手使这些递归调用更容易理解:现在对于单磁盘move
和多磁盘hanoi
,指定源和目标,并且没有第三个堆栈。
间为了简化
现在,如果你仔细看,你会发现,递归调用,始终是不相邻的堆栈。因此,如果您的堆栈顺序确实是源和目标不相邻,那么所有递归调用将使用我的代码的else
分支,并且可以缩短事情以避免区分大小写,并始终使用该分支。尽管如此,我发现上面更详细的代码更容易理解。
你能否告诉我们一些关于“相邻限制”是什么的? – 2013-03-21 10:09:54
移动只能从相邻的塔楼完成,所以如果我想从A-> B-> C – momigi 2013-03-21 10:12:36
解决此问题的算法在[本文]中给出(https:// tmft .wordpress.com /类别/类型/益智/塔的河内/页/ 2 /)。我可以尝试用Python编写它,但我不明白“source”代表的是什么。 – 2013-03-21 10:18:03