【Python實踐-3】漢諾塔問題遞歸求解(打印移動步驟及計算移動步數)


 1 # -*- coding: utf-8 -*-
 2 #漢諾塔移動問題
 3 # 定義move(n,a,b,c)函數,接受參數n,表示3個柱子A、B、C中第1個柱子A的盤子數量
 4 # 然后打印出把所有盤子從A借助B移動到C的方法
 5 def move(n,a,b,c):
 6     if n==1:
 7         print('move', a, '-->', c)
 8     else:
 9         move(n-1,a,c,b)
10         move(1,a,b,c)
11         move(n-1,b,a,c)
12 move(5,'A','B','C')
1 #計算移動步數
2 def f(n):
3     if(n==1):
4         return 1
5     else:
6         return 2*f(n-1)+1
7 print(f(4))

 

 
 
知識點:
遞歸函數一個函數在內部調用自身本身。 遞歸函數的優點是定義簡單,邏輯清晰。理論上,所有的遞歸函數都可以寫成循環的方式,但循環的邏輯不如遞歸清晰。 使用遞歸函數需要注意防止棧溢出解決遞歸調用棧溢出的方法是通過尾遞歸優化, 尾遞歸是指,在函數返回的時候,調用自身本身,並且,return語句不能包含表達式。但是 大多數編程語言沒有針對尾遞歸做優化,Python解釋器也沒有做優化, 任何遞歸函數都存在棧溢出的問題。
 
 
漢諾塔(Tower of Hanoi)源於印度傳說中,大梵天創造世界時造了三根金鋼石柱子,其中一根柱子自底向上疊着64片黃金圓盤。大梵天命令婆羅門把圓盤從下面開始按大小順序重新擺放在另一根柱子上。並且規定,在小圓盤上不能放大圓盤,在三根柱子之間一次只能移動一個圓盤。
a是起始柱,c是目標柱,b起到中轉作用, 在進行轉移操作時,都必須確保大盤在小盤下面,且每次只能移動一個圓盤,最終c柱上有所有的盤子且也是從上到下按從小到大的順序。
問題看起來並不復雜,當a柱子上只有一個盤子時只要把那個盤子直接移到c, 有兩個盤子的話把1號盤先移到b柱,在把2號盤移到c柱,最后把b柱上的1號盤移到c柱。
 
64個盤子,先把上方的63個盤子看成整體,等於只有兩個盤,只要完成兩個盤子的轉移,然后假設a柱只有63個盤子,與之前一樣的解決方式,前62個盤子先完成移動目標。就這樣一步步向前找到可以直接移動的盤子,62,61,60,......,2,1,最終,最上方的盤子是可以直接移動到c柱的,此時2號盤也能完成向c柱的轉移,這時c柱上時已經轉移成功的2個盤,於是3號盤也可以了,一直到第64號盤。
 
理解小tip,我是這么理解的,先看只有兩個盤子的移動方式:a-->b, a-->c, b-->c,之后盤子數增加,但都是基於兩個盤子的這種轉移方式,先將n-1個盤子移到中間柱b,此時等於中間柱b變成了目標柱,目標柱c變成了中間柱,所以此時是move(n-1,a,c,b)【可以看到b,c互換位置】,然后將1個盤子移到目標柱,即move(1,a,b,c),最后將n-1個盤子從b移到c,此時等於是將b看成起始柱,將a看成中間柱,所以是move(n-1,b,a,c),這樣就完成了移動。整個游戲中a為起始柱,b為中間柱,c為目標柱,在移動過程中,把一摞盤子從一個柱全部轉移到另一個柱子,那么當前所在的就是起始柱,要移去的就是目標柱,另一個柱子就是中間柱,都是相對的,體現在代碼中就是a,b,c參數位置的互換。結合網頁漢諾塔小游戲理解更佳哦~
 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM