1. 程式人生 > >第二章 演算法效率分析基礎 page 55 漢諾塔問題

第二章 演算法效率分析基礎 page 55 漢諾塔問題

漢諾塔問題介紹:        在印度,有這麼一個古老的傳說:在世界中心貝拿勒斯(在印度北部)的聖廟裡,一塊黃銅板上插著三根寶石針。印度教的主神梵天在創造世界的時候,在其中一根針上從下到上地穿好了由大到小的64片金片,這就是所謂的漢諾塔。不論白天黑夜,總有一個僧侶在按照下面的法則移動這些金片,一次只移動一片,不管在哪根針上,小片必在大片上面。當所有的金片都從梵天穿好的那根針上移到另外一概針上時,世界就將在一聲霹靂中消滅,梵塔、廟宇和眾生都將同歸於盡。

        這個問題有一個優雅的遞迴解法,圖2.4 描述了這個解法。為了把n > 1個盤子從木樁 1 移到木樁 3(藉助木樁2),我們需要先把 n -1 個盤子遞迴地從木樁 1 移到木樁 2(藉助木樁 3),然後直接把最大的盤子(第n

個盤子)從木樁 1 移到木樁 3 ,並且,最後把n -1個盤子遞迴地從木樁 2 移到木樁 3(藉助木樁 1 )。當然,如果n= 1,我們可以簡單地把這個單獨的盤子直接從一個木樁移到另一個木樁。

讓我們把前面的一般性方案應用到漢諾塔問題上去。顯然,我們可以選擇盤子的數量n作為輸入規模的一個指標,盤子的移動也可以作為該演算法的基本操作。可以清楚地看到,移動的次數M(n)只依賴於n,因此,對於M(n)有下列遞推等式:

                                                   當n> 1時,

                                                   M(n) = M (n -1) +I+ M (n -1)

另一個很明顯的事實是初始條件M (1) = 1,因此,對於移動次數M(n)我們建立了下面的遞推關係:

                                                   當n> 1時,

                                                   M(n)= 2M(n-l)+ 1

                                                   M (1) = 1

我們還是使用反向替換法來解這個遞推式:

M(n) = 2M(n-1)+ 1                                                                                替換M(n-1)=2M(n-2)+1

        = 2[2M (n -2) +1]+1 = 2^{2} M (n -2) + 2 + 1                                替換M(n-2) = 2M (n -3) + 1

        = 2^{2}[M (n -3) +1]+ 2 +1= 2^{3} M (n -3) + 2^{2} + 2 + 1

左邊前 3 個求和算式的模式預示著下一個算式將是:2^{4}M(n-4)+2^{3}+2^{2} +2+1,對這個模式進行一般化處理,在做了 i 次替換以後,得到下式:

M(n)=2^{i}M(n-i)+2^{i-1}+2^{i-2}+...+2+1=2^{i}M(n-i)+2^{i}-1

因為初始條件是在 n = 1 的情況下確立的,所以必須讓 i = n - 1,我們有下列方程來解遞推式(2.3):

M(n)=2^{n-1} M (n -(n -1)) + 2^{n-1}+1

M(n)=2^{n-1} M (1)+2^{n-1}-1=2^{n-1}+2^{n-1}-1=2^{n}-1

這樣得到了一個指數級的演算法,即使 n 的值不算大,該演算法的執行時間也會長得無法想像。這並不是因為這個演算法不好。不難證明,對於這個問題來說, 這是可能提供的最高效的演算法。事實上,是這個問題本身決定了它在計算上的難度。儘管如此,這個例子還是揭示了一個具有普遍意義的重要觀點:

我們應該謹慎使用遞迴演算法,因為它們的簡潔可能會掩蓋它們的低效率.

如果一個遞迴演算法會不止一次地呼叫它本身,出於分析的目的,構造一棵它的遞迴呼叫樹是很有用的。在這棵樹中,節點相當於遞迴呼叫,我們可以用呼叫引數的值(或者是幾個引數的值)作為節點的標記。對於漢諾塔這個例子來說,它的遞迴呼叫樹在圖2.5中給出。 通過計算樹中的節點數,我們可以得到漢諾塔演算法所做呼叫的全部次數:

C(n)=2^{n}-1

這個數字就像我們預測的那樣,和我們早先求得的移動次數是一致的。  

那麼好多人會問64個圓盤移動到底會花多少時間?那麼古代印度距離現在已經很遠,這64個圓盤還沒移動完麼?我們來通過計算來看看要完成這個任務到底要多少時間? 

我們使用通項式:C(n)=2^{n}-1 。當N=64時時 C(64)=18446744073709551615。 

我們假設移動一次圓盤為一秒,那麼一年為31536000秒。那麼18446744073709551615/31536000約等於584942417355天,換算成年為5845.54億年。 

目前太陽壽命約為50億年,太陽的完整壽命大約100億年。所以我們整個人類文明都等不到移動完整圓盤的那一天。

結論:漢諾塔問題通式如下

C(n)=2^{n}-1