汉诺塔问题解析 - 浅显易懂

汉诺塔问题

相传在古印度圣庙中,有一种被称为汉诺塔(Hanoi)的游戏。该游戏是在一块铜板装置上,有三根杆(编号A、B、C),在A杆自下而上、由大到小按顺序放置64个金盘(如图1)。游戏的目标:把A杆上的金盘全部移到C杆上,并仍保持原有顺序叠好。操作规则:每次只能移动一个盘子,并且在移动过程中三根杆上都始终保持大盘在下,小盘在上,操作过程中盘子可以置于A、B、C任一杆上。

——来自于百度百科

编程要求

  • 有A、B、C三根柱子,A为起始柱,B为辅助柱,C为目标柱,还有若干圆盘,圆盘按上小下大的顺序堆放在A柱上,从上到下依次为每一个圆盘标号为 1 到 n
  • 输入圆盘数,要求将A柱的圆盘移动到C柱,一次只能移动一个,但是要保证不能把大圆盘放在小圆盘上面
  • 输出每一个圆盘每一步移动的过程,比如:1号圆盘从 A -> C
  • 提示:利用递归解决

解题思路

从宏观的角度思考问题,不要试图去理解每一个圆盘的移动过程

首先,如果只有一个圆盘,那么就可以直接移动到目标柱子上,无需借助辅助柱,这一点就可以作为递归函数的终止条件

如果圆盘数量 n >= 2的时候,可以分3步考虑:

1.把n上面的所有圆盘移动到B柱,C作为辅助,此时A是起始柱,B是目标柱,C只是作为辅助柱

2.把最大的圆盘n直接从A移动到C柱

3.把B柱上的圆盘全部移到C柱,A作为辅助,此时B是起始柱,C是目标柱,A只是作为辅助柱

从宏观角度来看就是这3步,不需要去考虑n以外的圆盘怎么移动,因为每进入一次递归,起始柱、目标柱和辅助柱都会变化,我们很难分清每一步是从哪个柱子到哪个柱子的

那么n-1个圆盘的移动交给递归方法去解决即可,因此我们仅需要写出终止条件时的移动以及 n>=2时的3个步骤即可

宏观图示如下:

在这里插入图片描述

我们就可以利用递归来实现这段代码

我们首先需要定义一个方法

方法的功能是:传入n个圆盘,就能根据汉诺塔的规则,把目标盘子从 a -> c, b是辅助柱

在写递归的时候,我们只需要想着如何调用他来实现上述功能就好了,剩下的交给程序

代码实现

public class Test {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        System.out.println("请输入圆盘的数量");
        int num = in.nextInt();
        hanoi(num, 'A', 'B', 'C');//最开始以A、B、C分别作为起始、辅助、目标柱
    }
  	
  	//汉诺塔方法实现
    public static void hanoi(int num, char a, char b, char c){
      	//只有移动一个圆盘时
        if (num == 1) {
          	//不需要经过b,直接从a -> c
            System.out.println("第" + num + "个圆盘从" + a + " -> " + c);
        }else{
          	//n >= 2时,核心步骤1:把上面的num-1个圆盘从a -> b,c作为辅助
            hanoi(num - 1, a, c, b);
          	//核心步骤2:此时a上就剩下第num个圆盘,直接从a -> c
            System.out.println("第" + num + "个圆盘从" + a + " -> " + c);
          	//核心步骤3:此时再把b上的这n-1个圆盘从b -> c,a作为辅助
            hanoi(num - 1, b, a, c);
        }
    }

}
//执行结果
请输入圆盘的数量
31个圆盘从A -> C2个圆盘从A -> B1个圆盘从C -> B3个圆盘从A -> C1个圆盘从B -> A2个圆盘从B -> C1个圆盘从A -> C

总结

汉诺塔问题的代码,一定要从宏观角度去研究问题,如果从微观角度去看,研究每一个圆盘是如何移动,很难理解。其次,多用画图来帮助自己理解问题!!

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值