漢諾塔和遞迴
技術標籤:演算法
漢諾塔與遞迴
1.漢諾塔
規則如下:
在小圓盤上不能放大圓盤,在三根柱子之間一次只能移動一個圓盤.
圓盤從上到下一次標記為1、2、3.....n.
情況1:假設只有1個圓盤則只需要從A移動到C,總共移動1次。
情況2:假設只有2個圓盤則只需要把第1個移動到B,然後把第2個移動到C,最後再把第1個移動到C,總共移動3次。
情況3:**假設有3個圓盤則只需要把第1個移動到C,把第2個移動到B,再把第1個移動到B,接著把第3個移動到C,再把第1個移動到A,再把第2個移動到C,最後把第1個移動到C,總共7步。
......
可以從假設有2個圓盤和假設有3個圓盤這兩種情況的移動步驟中總結出一個規律:
類比情況3和情況2,可以把情況3步驟簡化為3步,想象第1個和第2個是一個整體,然後與第3個組成2個圓盤就變成了情況2,第一步把第1個和第2個這個整體放倒B柱上,第二步把第1個放到C柱上,第三步把第1個和第2個這個整體放到C柱上就完成。
可能會有疑問為什麼把第1個和第2個看做一個整體,注意我們這裡是簡化它的步驟,回到情況3,執行到第3步的時候是不是就相當於類比中第一步把第1個和第2個這個整體放倒B柱上。情況3執行到第4步的時候就相當於類比情況第二步把第1個放到C柱上。情況3中剩下的第567步相當於類比情況的第三步。
也就是說無論有多少個圓盤都可以像情況三中簡化為總共三個步驟。
那麼我們可以根據這觀察三步列出一個數學公式,假設n個圓盤移動F(n)次。還是用情況3來舉例子。那麼第一步把第1個和第2個這個整體放倒B柱上需要移動F(3-1)次,第二步把第1個放到C柱上,因為只有一個也只移動1次,第三步把第1個和第2個這個整體放到C柱上需要移動F(3-1)次。那麼總共移動多少次結果為:
F(3)=F(3-1)+1+F(3-1)
化簡得:F(3)=2*F(2)+1,但是這裡我們不知道F(2)和F(3)等於多少。但是我們知道圓盤只有一個時就是移動一次即F(1)=1。那麼我們可以計算情況2需要多少次,F(2)=F(2-1)+1+F(2-1)化簡為F(2)=2XF(1)+1,因為F(1)=1,代入得F(2)=3。得到了F(2)我們就可以得到F(3)=2X3+1=7次。
那麼當圓盤為n個時就可以根據三個步驟同理列出公式
F(n)=F(n-1)+1+F(n-1)=>F(n)=2*F(n-1)+1
又因為一個圓盤為1次,兩個圓盤為3次,3個圓盤為7次,根據1,3,7數字規律得出了一個快速計算漢諾塔次數的公式:2^n-1.
2.遞迴
編寫程式計算漢諾塔移動次數
我們可以根據公式:F(n)=2*F(n-1)+1利用遞迴原理來程式設計實現計算。把return看做=號,又因為計算機不知道F(0)等於多少,何時終結程式,所以加一個if條件語句告訴計算機F(0)=0。然後遞迴也涉及到了棧的原理,外部呼叫這個f函式時會把這個函式壓入棧,然後當return 2xf(n-1)+1時又呼叫了f函式,所以先把當前的函式再次壓入棧,直到n==0時,計算機知道F(0)=0了,那麼也就知道F(1)=1,然後就又知道F(2)....F(n),在這個過程中被壓入棧的函式也依次彈出來了。
int f(n){
if(n==0)
return 0;
else
return 2*f(n-1)+1;
}