汉诺塔问题
如下图所示,从左到右有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