漢諾塔問題
如下圖所示,從左到右有A、B、C三根柱子,其中A柱子上面有從小疊到大的n個圓盤,現要求將A柱子上的圓盤移到C柱子上去,期間只有一個原則:一次只能移到一個盤子且大盤子不能在小盤子上面,求移動的步驟和移動的次數?
這是一個經典的體現遞歸思想的案例。
假設將n個盤子由A挪至C需要的操作次數爲f(n),可以按以下步驟求解:
- 將n個碟子從A挪到C,等於先將最上面n-1個碟子經由C從A挪到B (操作次數即f(n-1)),
- 然後將A上剩餘的1個碟子放到C (操作次數1次)
- 最後再將B上的n-1個碟子經由A挪到C上 (操作次數f(n-1))
- 所以f(n) = 2f(n-1)+1,得出f(n)=2^n-1
Java代碼如下
public class Hanoi {
//操作步驟數
private static int steps = 1;
public static void main(String[] args) {
//盤子數目
int diskNumber = 4;
doTowers(diskNumber, 'A', 'B', 'C');
}
private static void doTowers(int diskNum, char from , char via, char to){
if (diskNum>1){
//針對盤子數目爲diskNum的盤子堆,先將最上面的diskNum-1個盤子(即Disk 1~Disk diskNum-1)挪至中轉位置
doTowers(diskNum-1, from, to, via);
//將剩餘的最下面的一個盤子(即Disk diskNum)直接一步挪到位
System.out.println("Step " + steps + ": " + "Disc" + diskNum + " " + from + "-->" + to);
steps++;
//將中轉位置的diskNum-1個盤子(即Disk 1~Disk diskNum-1)挪至終點位置
doTowers(diskNum-1, via, from, to);
}
//最上面那個碟子,即Disk1,從A挪到C
else {
System.out.println("Step " + steps + ": "+ "Disk1 " + from + "-->" + to);
steps++;
}
}
}
測試:以4個盤子爲例,運行結果如下。
Step 1: Disk1 A-->B
Step 2: Disc2 A-->C
Step 3: Disk1 B-->C
Step 4: Disc3 A-->B
Step 5: Disk1 C-->A
Step 6: Disc2 C-->B
Step 7: Disk1 A-->B
Step 8: Disc4 A-->C
Step 9: Disk1 B-->C
Step 10: Disc2 B-->A
Step 11: Disk1 C-->A
Step 12: Disc3 B-->C
Step 13: Disk1 A-->B
Step 14: Disc2 A-->C
Step 15: Disk1 B-->C