關於漢諾塔的一些思考-Python
漢諾塔規則
有三根杆子A,B,C。A杆上有 N 個 (N>1) 穿孔圓盤,盤的尺寸由下到上依次變小。要求按下列規則將所有圓盤移至 C 杆:
1.每次只能移動一個圓盤;
2.大盤不能疊在小盤上面。
漢諾塔的傳説
傳說越南河內某間寺院有三根銀棒,上串 64 個金盤。寺院裏的僧侶依照一個古老的預言,以上述規則移動這些盤子;預言說當這些盤子移動完畢,世界就會滅亡。
如何移動
如果n = 1 , 直接A -> C.
如果n = 2 , 稍稍複雜, A -> B, A -> C, B -> C.
…
Part1:
我們可以把移動n個金盤的問題分解爲三步驟:
1.把上面n-1個金盤從A柱移動到B柱上;
2.把第n個金盤從A柱移動到C柱;
3.最後把在B柱上的n-1個金盤移動到C柱上。
Part2:
至於如何將上面n-1個金盤從A柱移動到B柱上,我們又可以把問題分解為三步驟:
1.把上面n-2個金盤從A柱移動到C柱上;
2.把第n-1個金盤從A柱移動到B柱;
3.最後把在C柱上的n-2個金盤移動到B柱上。
Part3:
那麽問題又來了,如何將上面n-2個金盤從A柱移動到C柱上,我們又可以把問題分解為三步驟:
…
綜上,這就是很典型的大象放進冰箱只需三步驟,把冰箱門打開,把大象塞進去,把冰箱門關上。
到這,我們把這三根柱子換一個名字,稱之爲,發盤柱,中轉柱,目標柱。在上述Part1中,A是發盤柱,B是中轉柱,C是目標柱;在Part2中,A是發盤柱,B是目標柱,C是中轉柱…
所以,在一個遞歸過程中,發盤柱的存在是永恆不變的,但是中轉柱卻是在另外兩個柱子閒進行輪換。
移動n個金盤需要的步驟
設移動n個金盤所需步驟函數為F(n),則:
F(1) = 1 = 21 - 1.
F(2) = 3 = 22 - 1.
…
F(n) = F(n-1) + 1 + F(n-1) = 2F(n-1) + 1 = 2n - 1.
Python的遞歸實現算法-網傳寫法
def HanoTower(n, a, b, c): #a是發盤柱,b是中轉柱,c是目標柱
if n == 1 :
print(a, '-->', c) #遞歸終點,討論到只剩下一個盤子的問題時故不存在三柱問題,直接可從發盤柱->目標柱
else :
HanoTower(n-1, a, c, b) #第一個房間,把上面n-1個金盤從a柱移動到b柱,b、c之間輪換成為中轉柱,b為目標柱,直到只剩下一個盤子的問題,就可以開始移動了
print(a, '-->', c) #把第n-1個盤子從A->C
HanoTower(n-1, b, a, c) #第二個房間,把之前挪到b柱上的所有盤子移動到c柱,a=b是把b柱作為發盤柱,a、c輪換成為中轉柱,c為目標柱
print(HanoTower(3, 'A', 'B', 'C'))
關於遞歸的理解,如同俄羅斯套娃,每一層都是一樣的,所以可以把遞歸這個函數理解爲一個神奇的空間,例如HanoTower空间:
1、HanoTower空间特性为每个房间一模一样;
2、进入汉诺塔空间前选择携带的宝石数量,决定空间维度;
3、进入一个房间需消耗一颗宝石;
4、每个房间设置一名警卫,进入后寶石數量爲1才可离开返回上一個房間。
例如我們選擇携帶兩個寶石進入,有一個寶石為2的大房間,大房間裏面還有兩個寶石為1的小房間,依次順序執行。
另一個基於自己思考寫出來的Python實現
def Hano(n, a, b, c):
Hano1(n-1, a, c, b) #把上面n-1個金盤從發盤柱移動到中轉柱
print(a, '->', c) #把第n個金盤從發盤柱移動到目標柱
Hano2(n-1, b, a, c) #把上面n-1個金盤從中轉柱移動到目標柱
def Hano1(n, a, b, c):
if n == 1 :
print(a, '->', c) #直到問題規模變成1,執行移動金盤從發盤柱移動到目標柱
else :
Hano(n, a, b, c) #問題規模還不是1,繼續分解
def Hano2(n, a, b, c):
if n == 1 :
print(a, '->', c) #直到問題規模變成1,執行移動金盤從發盤柱移動到目標柱
else :
Hano(n, a, b, c) #問題規模還不是1,繼續分解
print(Hano(3, 'A', 'B', 'C'))
參考
[1].b站李永樂老師關於漢諾塔問題的思考;
[2].廖雪峰老師的Python教程.
来源:CSDN
作者:D00_552
链接:https://blog.csdn.net/D00_552/article/details/104172307