使用相邻限制解决tower of hanoi。 我试着环顾四周,但我找不到任何导致它。
到目前为止我尝试的是:
def hanoi(n, source, helper, target):
print "hanoi( ", n, source, helper, target, " called"
if n>0:
hanoi(n-1, source, helper, target)
if source[0]:
if source[0][-1] == 1:
move(source, helper)
move(helper, target)
else:
move(source, helper)
hanoi(n-1, target, helper, source)
hanoi(n-1, helper, target, source)
hanoi(n-1, source, helper, target)
def move(s, d):
disk = s[0].pop()
print "moving " + str(disk) + " from " + s[1] + " to " + d[1]
d[0].append(disk)
source = ([2,1], "source")
target = ([], "target")
helper = ([], "helper")
hanoi(len(source[0]),source,helper,target)
仅适用于2个磁盘。 感谢
我发现了这个很好的数学解释http://www.cse.cuhk.edu.hk/~chi/csc2110-2009/notes/T10.pdf
答案 0 :(得分:2)
乍一看,您似乎必须区分可以直接从当前源移动到当前目标的情况,以及必须分两步移动最大磁盘的情况。以下实现可以做到:
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
分支,并且您可以缩短事物以避免区分大小并始终使用else
1}}分支。然而,就发生的事情而言,我发现上面更详细的代码更容易理解。