分治算法_汉诺塔问题_Java实现

原文:https://blog.csdn.net/ljmingcom304/article/details/50296939


转载请注明出处:http://blog.csdn.net/ljmingcom304/article/details/50296939 
本文出自:【梁敬明的博客】

1.分治算法

  什么是分治算法?就是将一个难以解决的大问题,分割成一些规模较小并且相对独立的相同问题,以便各个击破,分而治之。

2.汉诺塔问题  

  汉诺塔问题是一个十分经典的可以通过分治算法解决的问题,存在A、B、C大小形同的3根石柱,其中A石柱从下往上按照大小顺序依次摆放着n个盘子,现在需要将A石柱的盘子全部移动到C石柱上,并且每次只能移动一个圆盘,小圆盘不能放在大圆盘上,请问该如何移动? 

汉诺塔
  

3.算法分析  

  当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(n1)∑1n(n−1)号圆盘,此时解决的就是将 n1(n1)∑1n(n−1)号圆盘和n号圆盘移动到石柱C的问题,即先将n1(n1)∑1n(n−1)号圆盘移动到石柱B,再将n号圆盘移动到石柱C,最后将n1(n1)∑1n(n−1)号圆盘移动到石柱C。因为将第n号圆盘移动到石柱C后,无论前n-1个圆盘怎么移动,都不需要再次移动第n号圆盘,即父问题与子问题相对独立且互不影响,因此可以将n1(n1)∑1n(n−1)号圆盘的问题同理向下拆分移动。 
  示例代码:

public class FZSFProblem {

    public static void main(String[] args) {
        solve(3);
    }

    public static void solve(int n) {
        // 已知条件n个圆盘和A、B、C三根石柱
        hanoi(n, "A", "B", "C");
    }

    /**
     * 若要让第n个圆盘成功从A移动到C,需要让前n-1个圆盘先从A移动到B,然后让第n个圆盘从A移动到C,
     * 最后让第n-1个圆盘从B移动到C,至于如何将前n-1个圆盘从A移动到B或者从A移动到C,仅仅是和父问
     * 题相同的子问题,采用父问题的解决方案即可。
     */
    private 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);
        }
    }

    private static void move(int n, String i, String j) {
        System.out.println("第" + n + "个圆盘," + "从" + i + "移动到" + j);
    }

}


猜你喜欢

转载自blog.csdn.net/notOnlyRush/article/details/80009105