一、问题描述
简单来讲,汉诺塔问题是这样的:
给定三根柱子,记为 A,B,C,其中 A 柱子上有 n 个盘子,从上到下编号为 1 到 n ,且上面的盘子一定比下面的盘子小。问:将 A柱上的盘子经由 B 柱移动到 C 柱最少需要多少次?
移动时应注意:① 一次只能移动一个盘子
②大的盘子不能压在小盘子上
二、思路讲解
我们从简单到复杂过程思考;
首先是n=1时
n=1时,我们只需要将盘子从A柱子移动一次到C柱子上
n=2时,此时分为3步:
- 将第一个盘子从A柱子放到B柱子
- 将第二个盘子从A柱子放到C柱子
- 将第一个盘子从B柱子放到C柱子
n=3时,此时分为7步:
- 将第一个盘子从A柱子放到C柱子上
- 将第二个盘子从A柱子放到B柱子上
- 将第一个盘子从C柱子放到B柱子(第二个盘子的上面)
- 将第三个盘子从A柱子放到C柱子上
- 将第一个盘子从B柱子放到A柱子上
- 将第二个盘子从B柱子放到C柱子上
- 将第一个盘子从A柱子放到C柱子上完成
现在我们思考一下当n>3时的情况,我们首先要注意的一点便是原先在A柱子上的最后一个盘子在最后一定是在C柱子上的最后一个,接下来的思想很重要:
我们将n个盘子分成两类:最后一个和除最后一个外所有的盘子,这样我们就会发现如果不考虑剩下n-1个盘子是如何移动的话,汉诺塔问题就会被我们简化为两个盘子的移动,那此时我们看到上面我们对于两个盘子的推导就会发现其实十分类似:
- 将n-1个整体移动到B柱子上
- 将最后一个移动到C柱子上
- 将n-1个整体移动到C柱子上
但我们可能会产生疑问,难道我们不用管那n-1个是咋移动的吗?我的回答是需要考虑,但我们是交给电脑取考虑,以n=3举个例子,你就会发现从第一步到第三步是将1,2两个盘子视作整体从A放到B,然后从第五步到第七步是将这个整体从B放到A,那他是如何放的,用一句话解释就是他是通过协助柱A将整体从起点柱子B转移到目标柱子C。
三、代码实现
public class Tower_of_Hanoi {
public static void hanoi(int num, char start, char end, char mid) {
if (num == 1) {
System.out.println("把第1个盘子" + "从" + start + "移助到" + end);
} else {
hanoi(num - 1, start, mid, end);
System.out.println("把第" + num + "个盘子从" + start + "移动到" + end);
hanoi(num - 1, mid, end, start);
}
}
public static void main(String[] args) {
int num = 3;
char start = 'A';
char mid = 'B';
char end = 'C';
hanoi(num, start, end, mid);
}
}
简单解释一下代码,本身看起来是分简单,实际上用的是递归的思想,n个盘子,首先按照我们的思路,要想将n-1个盘子移动,然后再把最后一个盘子移动,此时剩下盘子的数量就是n-1个,再按照思路将剩下的整体移动到C柱子上