分治演算法解決漢諾塔問題
阿新 • • 發佈:2021-02-20
一、漢諾塔問題概述
漢諾塔問題是一個古老而又有趣的問題。這個問題的具體內容是:將所有盤子從最左邊的塔 A 都移動到最右邊的塔 C 上。每次只能移動一個盤子,大的盤子不能壓在小的盤子上。
二、思路分析
我們先分別來看看只有一個、兩個、三個盤子的情況下,移動過程是怎樣的。
-
一個盤子
如上圖所示,一個盤子的移動過程為:
A → C A→C A→C -
兩個盤子
如上圖所示,兩個盤子的移動過程為:
A
→
B
A
→
C
B
→
C
A→B\\ A→C\\ B→C
A→BA→CB→C
-
三個盤子
如上所示,三個盤子的移動過程為:
從它們的移動過程,我們分析如下:
當只有一個盤子時,盤子直接 A→C
,過程非常簡單。
當有兩個盤子時,我們會首先把上面的盤子 A→B
,然後把最底下的盤子 A→C
,最後把上面的盤子 B→C
。
當有三個盤子時,我們可把最下面的一個盤子看作一部分,上面的兩個盤子看作另一部分,則相當於首先把上面一部分的盤子 A→B
,然後把最下面的盤子 A→C
,最後把上面一部分的盤子 B→C
當推廣到 N 個盤子時,我們可以將最下面的一個盤子看作單獨一部分,上面的 N-1 個盤子看作另外一部分。移動的思路可以概括為首先把上面 N-1 個盤子 A→B
,然後把最下面的盤子 A→C
,最後把上面 N-1 個盤子 B→C
。
那麼 N-1
個盤子是如何從塔 A 移動到塔 B 的呢?我們按照上面的思想,把 N-1 個盤子的最下面的盤子看作單獨一部分,上面的 N-2 個盤子看作另一部分,首先把上面 N-2 個盤子 A→C
,然後把最下面的盤子 A→B
,最後把上面 N-2 個盤子 C→B
。
接下來就是 N-2
個盤子的移動問題,依然是按照上面的思想…,直至分解到一個盤子的移動問題。
從上面的分析流程我們可以看到,解決漢諾塔問題的核心思想就是分治思想
三、程式碼實現
/**
* 分治思想解決漢諾塔問題
*/
public static void hanoitower(int num, char a, char b, char c){
if (num == 1){
System.out.println(a + "->" + c); // 只有一個盤子,直接 A->C 即可
}else{
hanoitower(num-1, a, c, b); // 把上面的 num-1 個盤子 A->B
System.out.println(a + "->" + c); // 把最下面的一個盤子 A->C
hanoitower(num-1, b, a, c); // 再把上面 num-1 個盤子 B->C
}
}