一個詳細的實施
乍一看它看起來好像你必須區分在那裏你可以從電流源直接移動到當前目標的情況下,以及那些必須分兩步移動最大磁盤的磁盤。下面的實現確實是:
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