算法学习|题目:破解汉诺塔游戏---将N个盘子以最小步骤移动到目的地,打印每一步的移动路径(基于Java)

题目:打印汉诺塔游戏移动路径(N个盘子)

知识补充:何谓汉诺塔游戏?

  • 汉诺塔:问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着 64片 黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上,并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
  • 为了更加生动地理解汉诺塔游戏,建议初学者可以百度🔍汉诺塔小游戏去体验一把(4399/7k7k都有,温馨提醒:不要借机撸上其他的小游戏!快回来学习!)
  • 汉诺塔游戏演示:将3个盘子从A移动到B,步骤如下图:
    汉诺塔游戏图解读者若不相信可以自己试试,上图所示的步骤是最佳路径,移动次数最少,为7次。

编程分析:递归实现

要求:将N个盘子从A柱子移动到B柱子,C为辅助柱子,打印每一步的移动路径
整体:将 1~N 号盘子从A移动到B,C为辅助

  • 分解步骤①:将 1~ (N-1) 号盘子从A移动到C,B为辅助 - - -此时A上只有N号盘子,B上没有盘子,C上有 1~(N-1) 号盘子
    分解步骤②:将N号盘子从A移动到B - - - 此时A上没有盘子,B上只有N号盘子,C上有第 1~(N-1) 号盘子
    分解步骤③:将 1~(N-1) 号盘子从C移动到B,A为辅助 - - - 此时 1~(N-1) 号盘子已经成功从A移动到B
    (因为B上的盘子是最大的,所以在移动C上的盘子时可以视为A、B均为空,不用担心 1~(N-1) 号盘子比B中盘子大的问题)

运用递归思想

  • 设函数 printHanoiTower(N,from,to,help) 表示打印 将N个盘子从from移动到to,以help为辅助 的每一步移动路径
  • 则分解步骤1可表示为(调用函数自己做): printHanoiTower(N-1,from,help,to)
  • 分解步骤2可表示为(这一步简单,手动做): System.out.println(“move” + N + “from” + from + “to” + to);
  • 分解步骤3可表示为(调用函数自己做): printHanoiTower(N-1,help,to,from)

(之所以分解步骤1与分解步骤3能够调用函数自身,是因为它们与原函数的处境一致:都是将 一堆盘子 从一个柱子移动到另一个柱子 并且除了开始盘子处于的柱子外 另外两个柱子相当于空)

代码展示:(看代码前最好先根据分析试着敲一下)

/*
	题目:破解汉诺塔游戏 --- 将N个盘子移动到目的地,打印每一步的移动路径
		将N个盘子从A移动到B,C为辅助
 */
public class HanoiTower {
	public static void main(String[] args) {
		//测试程序:打印将3个盘子从A移动到B的每个步骤,以C为辅助
		printHanoiTower(3,"A","B","C");
	}
	
	//函数printHanoiTower(int N,String from,String to,String help)的功能是
	//实现汉诺塔游戏,将N个盘子从from移动到to的每个移动步骤打印出来,其中help为辅助的
	//运用递归算法
	static void printHanoiTower(int N,String from,String to,String help) {
		//设置出口:
		//当N==1时,表示将1个盘子从from移动到to的移动步骤打印出来
		//移动完这个盘子,后面就没有盘子了,就可以跳出函数
		if(N == 1) {
			System.out.println("move " + N + "号盘子 from " + from + " to " + to);
			return;
		}
		
		//第一步:将1~(N-1)号盘子从from移动到help的每个移动步骤打印出来,其中to为辅助
		printHanoiTower(N-1,from,help,to);
		//第二步:将N号盘子从from移动到to的每个移动步骤打印出来(只有一步,自己做)
		System.out.println("move " + N + "号盘子 from " + from + " to " + to);
		//第三步:将1~(N-1)号盘子从help移动到to的每个移动步骤打印出来,其中from为辅助
		printHanoiTower(N-1,help,to,from);
	}
}


运行结果:(对照上述游戏演示图片,看结果是否相同)

运行结果展示

拓展题目:计算移动N个盘子所需的最小移动次数

找规律:(充分利用上一个程序HanoiTower)

找规律:通过演示上一段函数得到
N=1时 移动1次 - - - 21 - 1 = 1
N=2时 移动3次 - - - 22 - 1 = 3
N=3时 移动7次 - - - 23 - 1 = 7
N=4时 移动15次 - - - 24 -1 = 15
N=8时 移动255次- - - 28 - 1 = 255
则将N个盘子移动到另一个柱子上所需的最小移动次数为 2N - 1
(有小伙伴奇怪我是怎么得到的次数吗?数的!信吗?)
(将HanoiTower程序输出的结果复制粘贴到可以显示行数的文档编辑器或集成开发环境中<如Notepad++、eclipse…>)

代码实现:(过于简单,自己敲吧)

骚话时刻:
今天脑子里冒出一个想法:如果学习像吃饭一样简单就好了
怎么说呢?吃进肚子的食物有胃等各种器官自觉帮忙消化吸收营养,你可以睡觉、打游戏、看剧,想做啥做啥,毫不费力(当然前提是你没胃病咯)
但是学习呢
要不断思考不断理解不断复习不断加深记忆才能真正掌握,甚至曾经掌握过的知识,太久没有触碰,也会忘得一干二净。太悲惨了,希望自己脑子里长个能帮我消化吸收知识的“胃”,嘿嘿
不过呢
自我思考是一件贼有趣的事情
当你真正想明白一个难题的时候
这种成就感 可不是吃吃饭就能获得的
(今天的骚话有点正经 深夜毒鸡汤 来 一起干了它)

最后的最后,来看个小动图
汉诺塔动图

晚安,祝爱学习的孩子都能睡个好觉 😃

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值