分治法思想遞歸解決漢諾塔問題

分治思想

當我們求解某些問題時,由於這些問題要處理的數據相當多,或求解過程相當複雜,使得直接求解
法在時間上相當長,或者根本無法直接求出。對於這類問題,我們往往先把它分解成幾個子問題,找到
求出這幾個子問題的解法後,再找到合適的方法,把它們組合成求整個問題的解法。如果這些子問題還
較大,難以解決,可以再把它們分成幾個更小的子問題,以此類推,直至可以直接求出解爲止。這就是
分治策略的基本思想。

漢諾塔問題

漢諾塔問題是由很多放置在三個塔座上的盤子組成的一個古老的難題。如下圖所示,所有盤子的直 徑是不同的,並且盤子中央都有一個洞使得它們剛好可以放在塔座上。所有的盤子剛開始都放置在A 塔 座上。這個難題的目標是將所有的盤子都從塔座A移動到塔座C上,每次只可以移動一個盤子,並且任何 一個盤子都不可以放置在比自己小的盤子之上。
在這裏插入圖片描述
試想一下,如果只有兩個盤子,盤子從小到大我們以數字命名(也可以想象爲直徑),兩個盤子上 面就是盤子1,下面是盤子2,那麼我們只需要將盤子1先移動到B塔座上,然後將盤子2移動到C塔座,最 後將盤子1移動到C塔座上。即完成2個盤子從A到C的移動。
如果有三個盤子,那麼我們將盤子1放到C塔座,盤子2放到B塔座,在將C塔座的盤子1放到B塔座 上,然後將A塔座的盤子3放到C塔座上,然後將B塔座的盤子1放到A塔座,將B塔座的盤子2放到C塔座, 最後將A塔座的盤子1放到C塔座上。
以下是手畫的一個草圖:
在這裏插入圖片描述
如果有四個,五個,N個盤子,那麼我們應該怎麼去做?這時候遞歸的思想就很好解決這樣的問題 了,當只有兩個盤子的時候,我們只需要將B塔座作爲中介,將盤子1先放到中介塔座B上,然後將盤子2 放到目標塔座C上,最後將中介塔座B上的盤子放到目標塔座C上即可。
所以無論有多少個盤子,我們都將其看做只有兩個盤子。假設有 N 個盤子在塔座A上,我們將其看 爲兩個盤子,其中(N-1)~1個盤子看成是一個盤子,最下面第N個盤子看成是一個盤子,那麼解決辦法 爲:
1、先將A塔座的第(N-1)~1個盤子看成是一個盤子,放到中介塔座B上,然後將第N個盤子放到目標 塔座C上。
2、然後A塔座爲空,看成是中介塔座,B塔座這時候有N-1個盤子,將第(N-2)~1個盤子看成是一個 盤子,放到中介塔座A上,然後將B塔座的第(N-1)號盤子放到目標塔座C上。
3、這時候A塔座上有(N-2)個盤子,B塔座爲空,又將B塔座視爲中介塔座,重複1,2步驟,直到 所有盤子都放到目標塔座C上結束。
簡單來說,跟把大象放進冰箱的步驟一樣,遞歸算法爲: 1、從初始塔座A上移動包含n-1個盤子到中介塔座B上。 2、將初始塔座A上剩餘的一個盤子(最大的一個盤子)放到目標塔座C上。 3、將中介塔座B上n-1個盤子移動到目標塔座C上。

/**
* 漢諾塔問題
* @param dish 盤子個數(也表示名稱) * @param from 初始塔座
* @param temp 中介塔座
* @param to 目標塔座
*/
public static void move(int dish,String from,String temp,String to){
    if(dish == 1){
System.out.println("將盤子"+dish+"從塔座"+from+"移動到目標塔座"+to); }else{
move(dish-1,from,to,temp);//A爲初始塔座,B爲目標塔座,C爲中介塔座 System.out.println("將盤子"+dish+"從塔座"+from+"移動到目標塔座"+to);
}

測試:

move(3,“A”,“B”,“C”);
在這裏插入圖片描述

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