python學習筆記 // 以漢諾塔問題爲代表的遞歸思想

Hanoi Tower問題

相傳在古印度聖廟中,有一種被稱爲漢諾塔 Hanoi 的遊戲。該遊戲是在一塊銅板裝置上,有三根杆(編號A、B、C),在A杆自下而上、由大到小按順序放置若干金盤(如下圖 —— 圖片來自百度百科 )。
在這裏插入圖片描述

遊戲目標:

把A杆上的金盤全部移到C杆上,並仍保持原有順序疊好。

操作規則:

每次只能移動一個盤子,並且在移動過程中三根杆上都始終保持大盤在下,小盤在上,操作過程中盤子可以置於A、B、C任一杆上。

分析解決:

或許我們可以很容易的想明白當只有2個或3個盤子時的解決辦法,但當盤子數更多的時候,我們就很難具體列舉出移動盤子的每一步,這時我們的常規思維便顯得收效甚微,因此我們可以利用遞歸的思想來解決這個問題。

我們可以將漢諾塔問題進行簡化,設共有n個盤子,我們可以把複雜的解決辦法拆分爲如下三個步驟:

  • 將 n - 1 個盤子從 A 杆移到 B 杆 ( 將除了最底部的那個盤子以外的所有盤子看作是一個整體 )
  • 將第 n 個盤子從 A 杆移到 C 杆 ( 最底部的那個盤子)
  • 將 n - 1 個盤子從 B 杆移到 C 杆

以此類推,我們可以將 n 個盤子的移動問題轉化爲 n - 1 個盤子的移動問題,再轉化爲 n - 2 個盤子的問題,最終轉化爲 1 個盤子的移動問題。

按照搬動規則,必須有三個柱子才能完成搬動,一個柱子作爲搬動源,一個柱子作爲搬動目的地,另一個柱子在中間過渡使用。在搬動過程中,三個柱子的作用是動態變化的,因此在函數中三個柱子必須指定,令其作爲函數的參數。相關代碼如下:

print("規則:將所有的盤子從a柱移到c柱\n")
while True:
    num = int(input("請輸入盤子數:"))
    if (num <= 0):
        print("Error!")
        break
    count = 0
    def hanoi(num,a,b,c):
        global count
        if(num == 1):             #遞歸出口
            count += 1
            print("%d : %c -> %c" % (num,a,c))
        else:                     #遞歸式子
            hanoi(num-1,a,c,b)
            print("%d : %c -> %c" % (num,a,c))
            count += 1
            hanoi(num-1,b,a,c)
    hanoi(num,'a','b','c')
    print("需要移動的總次數爲:%d\n" % count)

在這裏插入圖片描述

歸納總結:

遞歸的實質就是把問題進行簡化,簡化成形式相同、但較簡單一些的情況,編寫程序時只需要給出統一形式的遞歸式子,到運行時再由計算機逐層展開。程序中每經歷一次遞歸,問題就得到進一步簡化,不斷的簡化下去,直至抵達遞歸出口,就停止遞歸了。
在運用遞歸思想時,最重要的就是要時刻提醒自己,編寫程序時只需要給出運算規律,具體實現細節應該讓計算機去處理。千萬不能鑽到細節的實現中去,否則就會陷入實現細節的泥沼中很難理清頭緒。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章