漢諾塔問題函數

漢諾塔問題

漢諾塔問題是一個經典的問題。漢諾塔(Hanoi Tower),又稱河內塔,源於印度一個古老傳說。大梵天創造世界的時候作了三根金剛石柱子,在一根柱子上從下往上按照大小順序摞着64片黃金圓盤。大梵天命令婆羅門把圓盤從下面開始按大小順序從新擺放在另外一根柱子上。而且規定,任什麼時候候,在小圓盤上都不能放大圓盤,且在三根柱子之間一次只能移動一個圓盤。問應該如何操做?html


分析

一股腦地考慮每一步如何移動很困難,咱們能夠換個思路。三根柱子依次爲a、b、c柱,如今目的是將a柱圓盤移動到c柱。python

先假設除最下面的盤子以外,咱們已經成功地將上面的63個盤子移到了b柱,此時只要將最下面的盤子由a移動到c便可。ide

當最大的盤子由a移到c後,b上是餘下的63個盤子,a爲空。所以如今的目標就變成了將這63個盤子由b移到c。這個問題和原來的問題徹底同樣,只是由a柱換爲了b柱,規模由64變爲了63。所以能夠採用相同的方法,先將上面的62個盤子由b移到a,再將最下面的盤子移到c……對照下面的過程,試着是否能找到規律:函數

1. 將b柱子做爲輔助,把a上的63個圓盤移動到b上
2. 將a上最後一個圓盤移動到c
3. 將a做爲輔助,把b上的62個圓盤移動到a上
4. 將b上的最後一個圓盤移動到c
5. ......

也許你已經發現規律了,即每次都是先將其餘圓盤移動到輔助柱子上,並將最底下的圓盤移到c柱子上,而後再把原先的柱子做爲輔助柱子,並重復此過程。htm

這個過程稱爲遞歸,即定義一組基本操做,這組操做將規模小一點(或大一點)的操做當作一個總體——無需關心它的細節,只當它已經完成了——而後執行剩下的操做。而在更小或更大的規模中也依此操做,直到規模達到預約值。blog


Python函數

在python中,咱們能夠用遞歸函數來計算漢諾塔問題的解決方案。遞歸

def move(n,a,b,c):
    if n == 1:
        print a, '-->', c    else:
        move(n-1, a, c, b)
        move(1, a, b, c)
        move(n-1, b, a, c)

>>> move(3,'A','B','C')A --> C
A --> B
C --> B
A --> C
B --> A
B --> C
A --> C>>> move(4,'A','B','C')A --> B
A --> C
B --> C
A --> B
C --> A
C --> B
A --> B
A --> C
B --> C
B --> A
C --> A
B --> C
A --> B
A --> C
B --> C

以 n=3 爲例,咱們來看看執行過程:圖片

在這裏插入圖片描述

如今咱們想一想,這個函數爲何這麼寫?反推一下:it

1. 當 n = 1 ,即 move(1,a,b,c) 時,移動過程是 A --> C ,因此函數能夠是

   move(1, a, b, c)

2. 當 n = 2 ,即 move(2,a,b,c) 時,移動過程是 
   
   A --> B
   A --> C
   B --> C ,
   
   因此函數能夠是

   move(1, a, c, b)         =       move(2-1, a, c, b)
   
   move(1, a, b, c)         =       move(1, a, b, c)
   
   move(1, b, a, c)         =       move(2-1, b, a, c)
   
3. 當 n = 3 ,即 move(3,a,b,c) 時,移動過程是
   
   A --> C
   A --> B
   C --> B
   A --> C
   B --> A
   B --> C
   A --> C ,
   
   因此函數能夠是
   
   move(1, a, b, c)
   move(1, a, c, b)         =       move(3-1, a, c, b)
   move(1, c, a, b)
   
   move(1, a, b, c)         =       move(1, a, b, c)
   
   move(1, b, c, a)
   move(1, b, a, c)         =       move(3-1, b, a, c)
   move(1, a, b, c)

4. 當 n = 4 ,即 move(3,a,b,c) 時,移動過程是
   
   A --> B
   A --> C
   B --> C
   A --> B
   C --> A
   C --> B
   A --> B
   A --> C
   B --> C
   B --> A
   C --> A
   B --> C
   A --> B
   A --> C
   B --> C ,
   
   因此函數能夠是
   
   move(1, a, c, b)
   move(1, a, b, c)
   move(1, b, a, c)
   move(1, a, c, b)         =       move(4-1, a, c, b)
   move(1, c, b, a)
   move(1, c, a, b)
   move(1, a, c, b)
   
   move(1, a, b, c)         =       move(1, a, b, c)
   
   move(1, b, a, c)
   move(1, b, c, a)
   move(1, c, b, a)
   move(1, b, a, c)         =       move(4-1, b, a, c)
   move(1, a, c, b)
   move(1, a, b, c)
   move(1, b, a, c)

5. 依次類推,當爲n時,須要 2^n-1 步才能完成整個移動過程,而函數能夠是

   move(n-1, a, c, b)
   move(1, a, b, c)
   move(n-1, b, a, c)

漢諾塔問題頗有意思,經過遞歸函數能夠簡單清晰的將其表示出來,遞歸實際上就是用本身來定義本身。class

相關文章
相關標籤/搜索