1. 程式人生 > >演算法詳解--漢諾塔

演算法詳解--漢諾塔

演算法由來
小故事
漢諾塔(Towers of Hanoi)是法國人M.Claus(Lucas)於1883年從泰國帶至法國的,河內為越戰時北越的首都,即現在的胡志明市;1883年法國數學家Edouard Lucas曾提及這個故事,據說創世
紀時Benares有一座波羅教塔,是由三支鑽石棒(Pag)所支撐,開始時神在第一根棒上放置64個由上至下依由小至大排列的金盤(Disc),並命令僧侶將所有的金盤從第一根石棒移至第三根
石棒,且搬運過程中遵守大盤子在小盤子之下的原則,若每日僅搬一個盤子,則當盤子全數搬運完畢之時,此塔將毀損,而也就是世界末日來臨之時。

我們來把這個故事變成一個演算法:
把三個柱子標為ABC 如果只有一個盤子時,將它直接搬到c,當有兩個盤子,就將B做為輔助。如果盤數超過2個,將第三個以下的盤子遮起來,就很簡單了,每次處理兩個盤子,也就是
A->B A->C B->C這三個步驟,而被遮住的部分是一個遞迴處理。如果有n個盤子,則移動完畢所需的次數為2^n-1。


如圖:
這裡寫圖片描述

事實上,若有n個盤子,則移動完畢所需之次數為2^n - 1,所以當盤數為64時,則所需次數為:

264- 1 = 18446744073709551615

為5.05390248594782e+16年,也就是約5000世紀,如果對這數字沒什麼概念,就假設每秒鐘搬一個盤子好了,也要約5850億年左右。
java程式碼實現:

package algorithm;

public class TowersofHanoi {
public static void main(String[] args) {
    alogr(4, 'a', 'b', 'c');

}
public  static
void alogr(int n ,char a ,char b ,char c){ if(n==1){ System.out.println("盤 " + n + " 由 " + a + " 移至 " + c); return; }else { alogr(n-1, a, c, b); System.out.println("盤 " + n + " 由 " + a + " 移至 " + c); alogr(n-1, b, a, c); } } }

執行效果當n=4的時候

1
a 移至 b 盤 2a 移至 c 盤 1 由 b 移至 c 盤 3a 移至 b 盤 1 由 c 移至 a2 由 c 移至 b 盤 1a 移至 b 盤 4a 移至 c 盤 1 由 b 移至 c 盤 2 由 b 移至 a1 由 c 移至 a3 由 b 移至 c 盤 1a 移至 b 盤 2a 移至 c 盤 1 由 b 移至 c

Hanoi塔問題, 演算法分析如下
設A上有n個盤子。
如果n=1,則將圓盤從A直接移動到C。
如果n=2,則:
(1)將A上的n-1(等於1)個圓盤移到B上;
(2)再將A上的一個圓盤移到C上;
(3)最後將B上的n-1(等於1)個圓盤移到C上。
如果n=3,則:
A)將A上的n-1(等於2,令其為n)個圓盤移到B(藉助於C),步驟如下:
(1)將A上的n
-1(等於1)個圓盤移到C上。
(2)將A上的一個圓盤移到B。
(3)將C上的n-1(等於1)個圓盤移到B。
B)將A上的一個圓盤移到C。
C)將B上的n-1(等於2,令其為n
)個圓盤移到C(藉助A),步驟如下:
(1)將B上的n-1(等於1)個圓盤移到A。
(2)將B上的一個盤子移到C。
(3)將A上的n
-1(等於1)個圓盤移到C。到此,完成了三個圓盤的移動過程。

總結
從上面分析可以看出,當n大於等於2時, 移動的過程可分解為三個步驟:第一步 把A上的n-1個圓盤移到B上;第二步 把A上的一個圓盤移到C上;第三步 把B上的n-1個圓盤移到C上;其中第一步和第三步是類同的。 當n=3時,第一步和第三步又分解為類同的三步,即把n’-1個圓盤從一個針移到另一個針上,這裡的n`=n-1。