转载自:http://blog.csdn.net/ljmingcom304/article/details/50296939
存在A、B、C大小形同的3根石柱,其中A石柱从下往上按照大小顺序依次摆放着n个盘子,现在需要将A石柱的盘子全部移动到C石柱上,并且每次只能移动一个圆盘,小圆盘不能放在大圆盘上,请问该如何移动?
算法分析:
当n=1时,也就是刚开始A石柱上仅仅摆放一个圆盘,那么直接将圆盘从A石柱上移动到B石柱上即可。
当n=2时,从上往下按照大小顺序将圆盘编为1号和2号,那么要将圆盘全部从石柱A移动到石柱C,首先需要将1号圆盘移动到石柱B,再将2号圆盘移动到石柱C,最后将1号圆盘移动到石柱C。
当n=3时,仍然从上往下按照大小顺序将圆盘编为1号、2号和3号,此时由于问题相对复杂,所以1号和2号圆盘看做一个圆盘,即1+2号圆盘,此时需要解决的就是将1+2号圆盘和3号圆盘移动到石柱C的问题,即先将1+2号圆盘移动到石柱B,再将3号圆盘移动到石柱C,最后将1+2号圆盘移动到石柱C即可。
由于每次只能移动一个圆盘,那么如果要将1+2号圆盘移动到石柱B,需要将1+2号圆盘拆分为两个个体,看做将1号和2号圆盘移动到石柱B,同理将1+2号圆盘移动到石柱C。
以此类推……
当n=n
时,将圆盘自上向下编为1号、2号、3号……n号,同理将1号到n-1
号圆盘看做一个圆盘,即 ∑n1(n−1)
号圆盘,此时解决的就是将 ∑n1(n−1)
号圆盘和n号圆盘移动到石柱C的问题,即先将∑n1(n−1)
号圆盘移动到石柱B,再将n号圆盘移动到石柱C,最后将∑n1(n−1)
号圆盘移动到石柱C。因为将第n号圆盘移动到石柱C后,无论前n-1个圆盘怎么移动,都不需要再次移动第n号圆盘,即父问题与子问题相对独立且互不影响,因此可以将∑n1(n−1)
号圆盘的问题同理向下拆分移动。
n=1时
第1个圆盘,从A移动到C
n=2时
第1个圆盘,从A移动到B
第2个圆盘,从A移动到C
第1个圆盘,从B移动到C
n=3时
第1个圆盘,从A移动到C
第2个圆盘,从A移动到B
第1个圆盘,从C移动到B
第3个圆盘,从A移动到C
第1个圆盘,从B移动到A
第2个圆盘,从B移动到C
第1个圆盘,从A移动到C
总结:
n个盘子和2个盘子或是3个盘子解决问题的形式都是一样的
将n-1个盘子有序地移动到B柱子上
将第n个盘子移动到C
将n-1个盘子从B柱子移动到C (这一步其实和将n-1个盘子从A柱子移动到C解决问题的形式是一样的)
假设是10个盘子从A移动到C。
按照分治思想,我们分解问题。
10个盘子从A移动到C = 9个盘子从A移动到B,1个盘子从A移动到C,9个盘子从B移动到C
=8个盘子从A移动到C,1个盘子从A移动到B,8个盘子从A移动到B,1个盘子从A移动到C,
8个盘子从B移动到A,1个盘子从B移动到C,8个盘子从A移动到C
注意:
10个盘子从A移动到C
9个盘子从A移动到B
8个盘子从A移动到C
等等这些过程将大问题拆分,直到拆分从1个盘子从某个柱子移动到另一个柱子
完全符合分治策略的特质。
/**
* 〈一句话功能简述〉<br>
* 〈功能详细描述〉
*
* @author wangzha
* @see [相关类/方法](可选)
* @since [产品/模块版本] (可选)
*/
public class HanoiTower {
public static void hanoi(int n, String a, String b,String c) {
if (n == 1) {
// 只有一个圆盘时直接从A石柱移动到C石柱
move(n, a, c);
} else {
// 将前n-1个圆盘从石柱A移动到石柱B
hanoi(n - 1, a, c, b);
// 将第n号圆盘从石柱A移动到石柱C
move(n, a, c);
// 将前n-1个圆盘从石柱B移动到石柱C
hanoi(n - 1, b, a, c);
}
}
public static void move(int n, String i, String j) {
System.out.println("第" + n + "个圆盘," + "从" + i + "移动到" + j);
}
public static void main(String[] args) {
hanoi(2,"A","B","C");
}
}