多柱漢諾塔最優算法設計探究

多柱漢諾塔最優算法設計探究

引言
漢諾塔算法一直是算法設計科目的最具代表性的研究問題,本文關注於如何設計多柱漢諾塔最優算法的探究。最簡單的漢諾塔是三個柱子(A、B、C),因此多柱漢諾塔的柱子個數M≥3。下面從三柱漢諾塔說起,慢慢深入我們要關心的問題。
1. 三柱漢諾塔
三柱漢諾塔是經典的漢諾塔問題,在算法設計中是遞歸算法的典型問題。其算法是這樣的: 首先把A 柱上面的n- 1 個碟子通過C 柱移到B 柱上【T(n-1)步】,然後把A 柱剩下的一個碟子移到C 柱上【1步】, 最後把B 柱上所有的碟子通過A 柱移到C 柱上【T(n-1)步】。很容易得到算法的遞歸方程爲:T(n)=2*T(n-1)+1,因此,不難算出步數是T(n)=2^n-1。對於三柱漢諾塔的算法的正確性自然是毫無爭議的,我們需要的是從三柱漢諾塔的設計中引申出多柱漢諾塔的設計方法。
2. 四柱漢諾塔
四柱漢諾塔並不是僅僅是多了一根柱子那麼簡單,所以我們先嚐試從正常的思維出發來探究如何使移動步數最少。
首先我們會想到,三柱漢諾塔需要藉助另一個柱子存放前n-1個盤子,再把第n個盤子移動到目的位置。順其自然的,四柱漢諾塔由於多了一個柱子,所以移動起來就更方便了,我們可以多留下一個盤子n-2,而不讓它借位到其他柱子直接移動到目的位置。這樣我們就得出算法的基本流程:
(1) 從A藉助C、D將 n-2個盤子移動到B上。
(2) 將n-2移動到C上。
(3) 將n-1移動到D上。
(4) 將n-2移動到D上。
(5) 從B藉助A、C將 n-2個盤子移動到D上。
另外,這麼設計是符合正常思維原則的。以爲隨着柱子的個數增多,我們希望每次移動的時候盤子儘可能不發生摺疊,也就是說我們希望除了需要藉助存放n-2個盤子的柱子。那麼剩下的兩個柱子可以允許至多兩個盤子不發生摺疊就能直接移動到目的位置,這樣才使得移動起來比較方便,步驟也會比較少。事實真的是如此嗎?我們具體分析一下算法。
按照以上設計的算法流程,我們得到遞歸方程:F(n)=2*F(n-2)+3。因此得到移動步數爲:F(n)=4*2^(n/2)-3:n爲奇數;F(n)=6*2^(n/2-1)-3:n爲偶數。下邊列出6個盤子的移動步數:
n 1 2 3 4 5 6
F(n) 1 3 5 9 13 21
到這裏,我們已經看出我們的設計的算法已經和經典的漢諾塔算法幾乎如出一轍了,甚至是如此的對稱和諧!基於此我們甚至可以推廣到M(M≥3)個柱子的情況,來得到我們希望的最優解,假設柱子編號爲1,2,3…M算法主題框架流程應該如下:
(1) 從1柱藉助3…M柱子將n-(M-2)個盤子移動到2柱上。
(2) 將M-2個通過3…M-1柱簡單的移動到M柱上【2*(M-2)-1步驟】。
(3) 從2柱藉助1,3…M-1柱子將n-(M-2)個盤子移動到M柱上。
具體步驟和四柱類似,不再做具體分析。這樣我們看到我們自己親手構建的算法模式如此完美,我們甚至不忍心去破壞它。但是我很遺憾的告訴自己,這種算法雖然正確,卻不是最優!!!比如,對於6個盤子4個柱子的漢諾塔,按照我們的想法是保留2個盤子進行移動。現在假如我們保留3個盤子,因此上邊的三個盤子按照4柱漢諾塔規則移動到B,步數應該是5(已經算出,可以驗證),剩下三個盤子按照3柱漢諾塔規則移動到D上,步數應該是2^3-1=7步,然後B上的三個盤子移動到D上仍然是5步,總步數爲5+7+5=17步<21步!現在我們可以確信的告訴自己,我們的想法太“天真”了。雖然我們想到讓盤子儘量不發生重疊來保證步數的最少,但是這並不能絕對保證。或許在盤子較少的情況下是可行的,但是盤子增多時,那些多餘的只有一個盤子的柱子是可以加以利用的。雖然這麼做加多了每次的移動步數,但是卻從另一個側面減少了遞歸的數量,因此我們需要從這裏邊找一個平衡點。
從上邊的例子中,我們得到一個啓示:在遞歸程序中剩餘盤子的個數並不一定是M-2,也有可能是M-1,我們假設剩餘盤子是M-r,那麼r到底取得多少才合適呢?其實,早在1941年,一位名叫J. S. Frame的人在《美國數學月刊》上提出了一種解決四柱漢諾塔問題的算法,這是人們熟知的Frame算法:
(1)用4柱漢諾塔算法把A柱上部分的n- r個碟子通過C柱和D柱移到B柱上【F( n- r )步】。
(2)用3柱漢諾塔經典算法把A柱上剩餘的r個碟子通過C柱移到D柱上【2^r-1步】。
(3)用4柱漢諾塔算法把B柱上的n-r個碟子通過A柱和C柱移到D柱上【F(n-r)步】。
(4)依據上邊規則求出所有r(1≤r≤n)情況下步數f(n),取最小值得最終解。
因此Frame算法的遞歸方程如下:
F(n)=min(2*F(n-r)+2^r-1),(1≤r≤n)。
通過這個方程我們能得到所有4柱漢諾塔的步驟個數,同時也有人證明[1]了,對於四柱漢諾塔,當r=(sqrt(8*n+1)-1)/2時,能保證f(n)取得最小值F(n)=(n-(r^2-r+2)/2)*2^r+1。所以算法的複雜度是F(n)=O(sqrt(2*n)*2^ sqrt(2*n))。從這這個方程中也可以看出,在n<6的時候,我們可以驗證是和我們起初的構想的結構是相同的,但是當n再增多時就不是當初想的那樣了。
3. 多柱漢諾塔
基於四柱漢諾塔的Frame算法,我們可以引申到多柱(M柱)漢諾塔的情況,我們簡稱M柱漢諾塔算法:
(1)用M柱漢諾塔算法把1柱上部分的n-r個碟子通過3…M柱移到2柱上【M( n- r )步】。
(2)用M-1柱漢諾塔算法把1柱上剩餘的r個碟子通過3…M-1柱移到M柱上【(r)步】。
(3)用M柱漢諾塔算法把2柱上的n-r個碟子通過1柱和3…M柱移到M柱上【M( n- r )步】。
(4)依據上邊規則求出所有r(1≤r≤n)情況下步數m(n),取最小值得最終解M(n)。
從4柱漢諾塔的遞歸方程和結果公示中我們可以看出,隨着柱子數量的增加,算法的複雜程度也是不斷地增加。對於解決M柱漢諾塔問題需要使用M-1柱漢諾塔的算法,因此除了算法解決問題需要遞歸外,算法的流程本身也需要遞歸,這種遞歸結構已經遠遠地複雜於當前所接觸的遞歸算法。如果有興趣可以嘗試去設計這種算法,算法所涉及的參數應該有盤子的個數n、柱子的個數m、算法的編號num、參數r等信息。因爲需要根據不同柱子情況下通過循環和遞歸找出最合適的r值,所以這種算法的複雜度肯定相當高。不過我們僅僅是爲了探究如何取得最優算法,所以具體實現就不再贅述了。
總結
通過以上的討論,我們從一般的思維——不折疊盤子,出發去找多柱漢諾塔的最優解,但是結果並沒有成功——盤子多時有可能柱子沒有充分利用。後來通過前人提出的Frame算法引申出多柱漢諾塔算法,並大致描述了多柱漢諾塔算法的雙重嵌套遞歸結構——算法問題的遞歸以及算法本身的遞歸實現。這種罕見的遞歸程序結構給我們在算法設計方面開闊了新的視野,希望不久的將來能找到更好地算法設計方法來解決多柱漢諾塔的問題。
參考文獻
1.《四柱漢諾塔之初步探究》楊楷 徐川( 北京大學計算機科學與技術系, 北京, 100871) 北京大學學報( 自然科學版) , 第40 卷, 第1 期, 2004 年1 月

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