问题描述:
设 A , B , C 是三个塔座,开始时 A 上有一叠共n个圆盘,这些圆盘自上而下,由大到小地叠在一起。各圆盘从大到小编号为1,2,···,n,先要求将塔座 A(原始塔座)上的这一叠圆盘移到塔座 B(目标塔座)上,并仍按同样的顺序叠置。在移动圆盘时应该遵守以下移动规则。
- 每次只能移动1个圆盘。
- 任何时刻都不允许将较大的圆盘压在较小的圆盘之上。
- 在满足规则1和规则2的前提下,可将圆盘移至 A , B , C 中任一塔座上。
输入 n ,输出 n 个圆盘从 A 移动到 B 的移动过程。
解题思路:(采用递归的方法)
一、 第一次递归:
-
当n=1时只要将编号为 1 的圆盘从 A 移动到 B 上即可。
-
当n>1时需要利用 C 作为辅助塔座。此时可将问题分解为三个子问题:
①. 先将前 n-1 个圆盘从 A 移动到 C(辅助塔座)上;
②. 然后将第 n 个圆盘从 A 移动到 B(目标塔座)上;
③. 最后将在 C 上的前 n-1 个圆盘从 C 再移动到 B (目标塔座)上。
二、 第二次递归:
该方法将 n 个圆盘移动问题分解为两个(①和③)前 n-1 个圆盘移动到子问题,根据这种思想,可以继续再将前 n-1 个圆盘移动的两个子问题分解为 4 个 n-2 个圆盘移动的子问题:
-
分解子问题①(为实现将前 n-1 个圆盘从 A 移动到 C 上,此时 C 为目标塔座,B 为辅助塔座):
①. 先将前 n-2 个圆盘从 A 移动到 B(辅助塔座)上;
②. 然后将第 n-1 个圆盘从 A 移动到 C(目标塔座)上;
③. 最后将在 B 上的前 n-2 个圆盘从 B 再移动到 C(目标塔座)上。
-
分解子问题②:
当前 n-1 个圆盘移动到 C 上后,此时 A 上只剩 第 n 个圆盘,此时可以看成 n=1 的情况。
-
分解子问题③(为实现将在 C 上的前 n-1 个圆盘从 C 再移动到 B上,此时 B为目标塔座,A 为辅助塔座):
①. 先将前 n-2 个圆盘从 C 移动到 A(辅助塔座)上;
②. 然后将第 n-1 个圆盘从 C 移动到 B(目标塔座)上;
③. 最后将在 A 上的前 n-2 个圆盘从 A 再移动到 B(目标塔座)上。
注意:该算法的执行顺序为(以下面代码中的语句为例):
代码实现:
import java.util.Scanner;
public class 分治_5Hanoi塔问题
{
public static void move(int n, char a, char b)
{
System.out.println("第 " + n + " 个盘:" + a + " -> " + b);
}
public static void Hanoi(int n, char start, char end, char mid)
{
if (n==1)
move(n - 1, start, end);
else
{
Hanoi(n - 1, start, mid, end);
move(n - 1, start, end);
Hanoi(n - 1, mid, end, start);
}
}
public static void main(String[] args)
{
// TODO 自动生成的方法存根
Scanner input = new Scanner(System.in);
int n = input.nextInt();
input.close();
Hanoi(n, 'A', 'B', 'C');
}
}