分治算法-汉诺塔问题

分治算法

分治算法的设计思想

  1. 分解
    将原问题分解成若干个规模较小的、相互独立的、与原问题形式相同的子问题;
  2. 解决
    当子问题规模小到一个程度可以直接求解的时候直接解,否则往下递归求解;
  3. 合并
    将各个子问题的解合并为源问题的解

汉诺塔问题

  1. 如果是手动操作的思路分析(比如4个盘)

    • 如果想把A柱上4个盘全部移到C柱,则首先需要将最下面的盘移到C柱, 就需要将上面3个圆盘先移到B柱;
    • 如果想把A柱上面3个盘的最下面一个盘(倒数第二个)移到B柱,就需要先将上面2个盘移到
      C柱;
    • 如果想把A柱上面2个盘的最下面1个盘(倒数第三个)移到C柱,就需要先将上面1个盘移到B柱
      至此,就得到了第一步应该怎么走!
  2. 分治算法思路分析
    源问题就是将A柱上的N个盘借助B柱移到C柱,则可以将其分解成:

    • 将上面的N-1的盘子放到B柱
    • 将最下面的一个盘子放到C柱
    • 再将B柱上面的N-1个盘子放到C柱
      比如,当上面 N-1 = 1的时候,即问题规模已经是2,则可以先将上面1个盘子
      放到B,再将下面的盘子放到C柱,最后将B柱的1个盘子放到C柱,完成!
      其实不管上面N-1是多少,不管上面有多少个盘子(>=1),即问题规模>=2的时候,都可以将其看作是1个盘子,
      然后都是递归执行上述3步走策略。
      直到问题规模为1的时候就可以直接将这1个盘子从A柱子移动到C
      柱子,因此问题规模为1是递归退出的条件

      还要注意的是:当A柱上面 N-1 个盘子放到 B柱的时候,下一步就要想先将B柱上面N-2个移到A
      柱,再将B柱上最下面的放到C柱,然后将A柱N-2个盘子放到C柱。
      因此这里的A、B、C三个柱子在代码中不能特指某个柱子,而应该表示
      • A:源柱子
      • B:中间辅助柱子
      • C:目的地柱子
  3. 代码思路分析

    1. 只要当前问题规模(盘子数num为1),就直接将盘子从源柱子A => 目的地柱子C

    2. 其他各种情况的问题规模(盘子数num>=2),都是

      • 先将上面的num-1个盘子从源柱子A 借助目的地柱子C 移到辅助柱子B上
      • 然后将最下面的1个盘子直接从源柱子A => 目的地柱子C
      • 最后将辅助柱子B上的num-1个盘子借助源柱子A 移到目的柱子C上

      就这样递归的执行

public class HanoiTower {
    public static void main(String[] args) {
        move(4, 'A', 'B', 'C');
    }

    // 汉诺塔的移动方法
    // 使用分治算法
    public static void move(int num, char a, char b, char c) {
        // 如果只有1个盘
        if(num == 1) {
            System.out.println("第1个盘 " + a + " => " + c);
        } else {
            move(num - 1, a, c, b);
            System.out.println("第" + num +"个盘 " + a + " => " + c);
            move(num - 1, b, a, c);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值