汉诺塔问题和爬楼梯(递归)

c21bbdfb26934bd29c2db8b5abf383de.png

感谢大佬的光临各位,希望和大家一起进步,望得到你的三连,互三支持,一起进步

个人主页LaNzikinh-CSDN博客

c语言基础_LaNzikinh篮子的博客-CSDN博客

文章目录 

  • 一.爬楼梯问题
  • 二.汉诺塔问题
  • 总结

 

一.爬楼梯问题

 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?注意:给定 n 是一个正整数

这个问题就是一个非常典型的递归问题,但是拿到题目的时候真的没有什么思路,不知道怎么去思考

思路:

递归的核心思想就是把大问题变成小问题,我们先来找爬楼梯的小问题,最简单的就是爬一个或者爬两个,那我爬n个怎么说呢?我爬到第N个有两种上去的方法,一种是在N减一个的时候爬一个楼梯,另一种就是在N -2个的时候爬两个楼梯,所以是f(n)=f(n-1)+f(n-2)

617965bc867b47c0a1ea82f217c1793d.png

int fun(int n)
{
	if (n == 1)
		return 1;
	else if (n == 2)
		return 2;
	else
		return  f(n - 1) + f(n - 2);
}

这里用的是深度优先遍历,这个还是比较简单的

 

二.汉诺塔问题

d0ca265b87624c0f8c675d09a503032c.png

游戏的规则:汉诺塔游戏规则如下12:

  • 有三根相邻的柱子,标号为A,B,C。
  • A柱子上从下到上按金字塔状叠放着n个不同大小的圆盘。
  • 现在把所有盘子一个一个移动到柱子B上,并且每次移动同一根柱子上都不能出现大盘子在小盘子上方。
  • 每次只允许一个人移动碟子,且每次仅允许移动一个碟子的位置。
  • 在团队所有成员必须依次移动盘子。
  • 在任意一次移动中,较小的盘子不得被置于较大的盘子下方。
  • 一次只能移动一个圆盘。

思路:A为起始柱子,B为中转柱子,C为目标柱子

注意:这些柱子在递归是会发生改变!!!

dd32d5f35a614da88370857c9a610490.png

要想完成这个问题,首先得把上面两个放到中间去

627579e3c6bb412ba44f3ef750eb14de.png

 

然后再把最底下的放到目标地方

642fe4f5b8344caab433a75d86891eca.png

再把中间的放到目标上就可以了

2da65a66667043bbb226a55ecd8c2210.png

函数递归很好写,但是非常难理解

void hanoi(int n, char A, char B, char C) {
    //n代表  A柱子上面的盘子数量
    if (n == 1) {
        move(n, A, C);//如果只有一个盘子,直接从A移动到C
    }
    else {
        hanoi(n - 1, A, C, B);//将n-1个盘子从A移动到B
        move(n, A, C);
        hanoi(n - 1, B, A, C); //将n-1个盘子从B移动到C
    }

}

move为打印函数

void move(int n, char x, char y) {
    printf("%c--->%c\n",x, y);
}

很多人理解了思想也写得出这个代码,但是就是想不通为什么完成了这个题目?

我觉得可能是因为没理解程序里面的参数是怎么回事,else里面的参数估计就有人看不明白了,在你第一次在主函数中把A,B,C 这三个字符输进去的时候,调用函数是没问题的,形参和实参一一对应,hanoi函数里面的A,B,C就对应着'A', 'B','C'三个柱子,但是你一旦开始递归,第一次递归函数里面的三个参数A,B,C代表的就是柱子'A',柱子'C',柱子'B'  了,每一次递归A,B,C三个参数代表的柱子都在不断的跳动,所以函数printf里面的从A到C进行输出,其实真正打印出来的各种移动情况都有,而else里面的第一句话执行完毕后,就是实现了把第一个柱上除了最后一个盘子上面的所有盘子移到了B,第二句其实是最初的参数和柱子对应的A和C,即把最后一个从A移到C,第三句又是把所有的从B移到C。函数本身参数是定死的,但是那三个参数却可以代表不同的真实的具体哪个柱子上的盘子进行移动,而参数的位置代表的是移动的思想。


总结

这两个问题是很好的递归问题,递归难就难在写出来简单,但是真正理解起来还是有一定的思考量的

 

  • 114
    点赞
  • 80
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 76
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LaNzikinh篮子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值