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

时间:2021-03-14 11:19:59

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

1.分治算法

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

2.汉诺塔问题  

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

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

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

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);
}

}