密室逃脱游戏-第12届蓝桥杯省赛Python真题精选

[导读]:超平老师的Scratch蓝桥杯真题解读系列在推出之后,受到了广大老师和家长的好评,非常感谢各位的认可和厚爱。作为回馈,超平老师计划推出《Python蓝桥杯真题解析100讲》,这是解读系列的第58讲。

密室逃脱游戏,本题是2021年4月24日举办的第12届蓝桥杯青少组Python编程省赛真题,第12届一共有两场省赛,这是第二场。题目要求计算在100间密室中,按照游戏规则进入M号密室有多少种路线方案。

先来看看题目的要求吧。

一.题目说明

提示信息:

有一个密室逃脱游戏,有100间密室连在一排。密室编号是从1开始连续排列一直排到第100间密室,如下图:

图片

游戏规则:

1. 玩家初始位置在1号密室;

2. 每次玩家可以进入右边的一个密室,也可以跳过一个密室进入下个密室(如:当玩家当前在3号密室,他可以进入4号密室也可以进入5号密室);

3. 有毒气的密室不能进入需要避开。

编程实现:

给定三个正整数X,Y,M(X < Y < M ≤ 100),表示三个密室编号,X号密室和Y号密室有毒气泄漏,不能进入,玩家需要进入到M号密室。按照游戏规则进入M号密室有多少种路线方案。

例如:X = 2,Y = 4,M = 7,进入M号密室有2种路线方案,分别是1->3->5->6->7路线和1->3->5->7路线。

输入描述:

输入三个正整数X,Y,M(X < Y < M),X和Y表示有毒气密室编号,M表示需要进入的密室编号,且三个正整数之间以英文逗号隔开

输出描述:

输出进入M号密室有多少种路线方案

样例输入:

2,4,7

样例输出:

2

二.思路分析

这是一道算法题,考查的知识点涉及循环、递归、列表和斐波那契数列等。

题目所描述的场景看起来是不是有似曾相识的感觉,但是又感觉有点怪怪的?实际上,这就是斐波那契数列(兔子数列)的变种问题,其本质仍然是斐波那契数列。

还记得斐波那契数列的递推公式吗:

图片

针对本题,我们可以运算分解思维将题目需求拆分成两步:

1). 假定没有毒气密室;

2). 增加X和Y两个毒气密室。

如果不考虑毒气密室,这就是我们熟悉的斐波那契数列,我们可以使用f(m)表示进入M号密室的路线数量。

当m = 3时,也就是3号密室,可以从1号密室过来,也可以从2号密室过来,根据加法原理,f(3) = f(1) + f(2)。

对于2号密室,它前面只有1号密室,因此路线数量为1,即f(2) = 1。

对于1号密室,它是玩家的初始位置,应该设置为多少呢?

如果只看1号密室本身,我们可以设置为0,也可以设置为1。但是从3号密室的角度来看,设置为1显然更合适。

所以,递推公式如下所示:

f(m) = 1 当m = 1 或 m = 2时f(m) = f(m - 1) + f(m - 2) 当m > 2时

如下图所示,这是在没有毒气密室时1~8号密室的路线数量:

图片

接下来,我们再增加两个毒气密室X和Y,以题目给的样例数据X = 2,Y = 4,M = 7来说明。

X号密室和Y号密室有毒气泄漏,是不能进入的,这就意味着f(x)和f(y)都为0,即f(2) = f(4) = 0。

所以,在计算f(m)的时候,除了要单独考虑f(1)和f(2)之外,还需要考虑m = x、m = y的情况,如果 m = x 或者 m = y,那么f(m) = 0。

对应的,进入1~8号密室的路线数量如图所示:

图片

这就意味着在计算每个密室的路线数量时,需要判断房间号是否为x或y,递推公式如下:​​​​​​​

f(m) = 0  当m = x 或 m = yf(m) = 1  当m = 1 或 m = 2f(m) = f(m - 1) + f(m - 2) 当m > 2时

针对斐波那契数列问题,通常有如下三种解决方案:

1). 递归

2). 动态规划

3). 迭代

这3种方案,都有一个共同点,那就是都需要用到递推公式。

思路有了,接下来,我们就进入具体的编程实现环节。

三.编程实现

根据上面的思路分析,我们分别使用3种方案来编写程序:

  • 递归

  • 动态规划

  • 递推

1. 递归

递归算法的核心是要定义递归函数,递归的3要素如下:

  • 自定义函数,并且带有参数

  • 在函数中调用自己

  • 有结束条件

根据前面思路分析中的递推的公式,编写代码如下:

图片

代码比较简单,这也是递归函数的特点,强调两点:

1). m = x或y的条件,要先于m == 1或2;

2). 在if语句中有return语句,因此不需要使用elif和else,代码更加简洁。

但是,这个代码是有问题的,如果m比较大的话,会存在超时的情况,你可以测试一下m为100的情况。

为什么会超时呢,原因在于进行了大量重复的计算,比如在计算f(x, y,10)的时候,需要计算f(x, y, 9)和f(x, y, 8),而在计算f(x, y, 9)的时候,需要计算f(x, y, 8)和f(x, y, 7),很显然,f(x, y, 8)计算了两次。

实际上,随着m的增加,计算的次数会以指数的形式增加。能否将这些已经计算过的值保存起来,从而避免重复计算呢。

这就是带备忘录的递归算法,可以增加一个列表,用于保存f(x, y, m)的值。

修改代码如下:

图片

说明两点:

1). 递归函数中增加了一个参数memo,这就是备忘录列表;

2). 将列表的初始值设为-1,然后判断memo[m]的值,如果为-1,则说明是第一次计算,将计算的结果保存到memo列表中。

有了带备忘录的递归算法,时间复杂度将大大降低,效率会得到极大的提升,这是典型的用空间换时间的策略。

2. 动态规划

递归算法是自顶向下的策略,而动态规划则是自底向上的思想,可以从第1项和第2项开始,逐个计算后续的每一项。

动态规划有两个关键点:

  • 定义dp列表

  • 找出推导公式(状态转移方程)

我们可以定义dp[i]表示到i号密室的路线数量,由于列表的下标是从0开始的,为了方便,将dp[0]设为0,表示0号房间,可以理解为是虚拟的一个房间,dp[1]设置为1,表示1号房间,依此类推...

对应的代码如下:

图片

代码也不算多,说明两点:

1). 在计算dp[1]的时候,使用了带条件的赋值语句,这体现了Python的简洁性;

2). 虽然列表有第0项,但它是虚拟的,实际上我们是从第1项开始算的,即下标为1的列表项表示1号密室,因此对于m号密室,就是dp[m]。

3. 递推

仔细分析动态规划中的代码,可以发现在计算dp[i]的时候,实际上只用到了dp[i - 1]和dp[i - 2]。

于是,一些追求完美的同学开始有想法了,能否不用列表呢,这样还可以节省不少空间呢。

确实可以,实际上,我们只需要3个变量就够了,不妨用fm表示当前项,f2表示第m -1项,f1表示第m - 2项。

接下来使用循环从第3项开始,一步一步的计算每一项,这就是递推的算法思想,也叫迭代,对应的代码如下所示:

图片

代码不多,说明两点:

1). 在计算第1项和第2项的时候,需要考虑x和y的取值;

2). 每次在计算好当前项fm的值后,需要重新设置f1和f2,可以理解为f1和f2都右移一位。

至此,整个程序就全部完成了,你也可以输入不同的数字来测试效果啦

四.总结与思考

本题代码在10行左右,涉及到的知识点包括:

  • 循环语句,主要是for...in;

  • 条件语句;

  • 输入处理,尤其是多个数据的输入;

  • 列表的使用;

  • 带条件的赋值语句;

  • 斐波那契数列;

作为本次省赛的倒数第二题,难度较大,难点在于如何找到突破点,将问题拆分成两个小问题,然后逐一解决。

将复杂问题拆分成多个简单问题,进而逐个解决,这是我们在学习编程时要重点培养和训练的一种思维。

任何复杂问题,只要能分解,我们就可以找到解决问题的方法。

号称硅谷钢铁侠的埃隆·马斯克曾经说过:“一个人最大的本事是拥有拆解思维,掌握它,你将活力四射”,由此可见,拆解思维是多么的强大和重要。

斐波那契数列,这是我们学习算法的必备经典问题,本文给出了3种解决方案,分别是递归、动态规划和递推(迭代)。相比较而言,递推算法是最优的,时间复杂度和空间复杂度都是最低的。

当我们彻底理解了斐波那契数列问题,就可以解决一系列相关题目,基本上都是它的变种问题。

超平老师给你留一道思考题,这里给出了动态规划的解决方案,你认为斐波那契数列是一个真正的DP问题吗,为什么呢?

你还有什么好的想法和创意吗,也非常欢迎和超平老师分享探讨。

如果你觉得文章对你有帮助,别忘了点赞和转发,予人玫瑰,手有余香😄

需要源码的,可以移步至“超平的编程课”gzh。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/675813.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【iOS】——浅析CALayer

文章目录 一、CALayer介绍二、UIview与CALayer1.区别2.联系 三、CALayer的使用1.初始化方法2.常用属性 四.CALayer坐标系1.position属性和anchorPoint属性2.position和anchorPoint的关系3.position、anchorPoint和frame的关系 五、CALayerDelegate六、CALayer绘图机制1.绘图流程…

stripe支付

使用第一个示例 1、示例中的PRICE_ID需要去Stripe控制台->产品目录创建产品 1、 添加产品 2、点击查看创建的产品详情 4、这个API ID就是demo中的PRICE_ID 注意&#xff1a;需要注意的是&#xff0c;测试模式和生产模式中的 $stripeSecretKey 需要对应上。简而言之就是不能生…

Apple OpenELM设备端语言模型

Apple 发布的 OpenELM&#xff08;一系列专为高效设备上处理而设计的开源语言模型&#xff09;引发了相当大的争论。一方面&#xff0c;苹果在开源协作和设备端AI处理方面迈出了一步&#xff0c;强调隐私和效率。另一方面&#xff0c;与微软 Phi-3 Mini 等竞争对手相比&#xf…

Angular中创建和使用服务

Angular中的服务 文章目录 Angular中的服务前言一、创建服务二、使用服务 前言 Angular 服务是 Angular 应用程序中用于封装可重用逻辑的类。服务在应用程序的多个组件之间共享数据和功能&#xff0c;而不依赖于应用程序的UI。服务可以用于诸如数据处理、与后端通信、用户身份…

Linux初识

1.操作系统的那点事 &#xff08;1&#xff09;结论&#xff1a;操作系统是作软硬件管理的软件&#xff1b; &#xff08;2&#xff09;计算机是操作系统&#xff0c;设备驱动&#xff0c;硬件三个相互结合发挥作用的&#xff0c;操作系统是用来管理硬件的&#xff0c;常见的…

免费https证书申请

HTTPS证书&#xff0c;也称为SSL证书&#xff08;Secure Sockets Layer&#xff09;或TLS证书&#xff08;Transport Layer Security&#xff09;&#xff0c;是一种数字证书&#xff0c;用于在互联网通信中确保数据传输的安全性、完整性和真实性。它是基于公钥基础设施&#x…

【Markdown笔记】——扩展语法学习part3 表格脚注标题编号(锚点)列表删除线人物列表(todo列表)emoji等

【Markdown笔记】——扩展语法学习part3 表格&脚注等 MarkdownMarkdown 表格语法表格内容居中、左对齐、右对齐 Markdown 脚注语法Markdown 标题编号语法Markdown 列表语法Markdown 删除线语法Markdown 任务列表语法Markdown 使用 Emoji 表情 前几篇markdown相关博客&#…

S型曲线的几种设计(图像对比度调节)

一般来讲&#xff0c;图像调色模块都会提供“曲线”工具&#xff0c;这是一个极其灵活的功能&#xff0c;绝大部分的调色都可以通过该工具实现&#xff0c;但是曲线功能的交互相对而言比较复杂。出于简便性和效率方面的考量&#xff0c;调色模块往往还会提供一些具有很强的功能…

如何更好地使用Kafka? - 运行监控篇

要确保Kafka在使用过程中的稳定性&#xff0c;需要从kafka在业务中的使用周期进行依次保障。主要可以分为&#xff1a;事先预防&#xff08;通过规范的使用、开发&#xff0c;预防问题产生&#xff09;、运行时监控&#xff08;保障集群稳定&#xff0c;出问题能及时发现&#…

超声波测距传感器--第七天

1.超声波测距 型号:HC-SR04 接线参考:模块除了两个电源引脚外,还有TRIG,ECHO引脚,这两个引脚分别接我们开发板的P1.5和P1.6端 超声波模块是用来测量距离的一种产品,通过发送超声波,利用时间差和声音传播速度,计算模块到前方障碍物的距离。 2. 如何让它发送波: Tri…

微软 AI 研究团队推出 SIGMA:一个开源研究平台,旨在推动混合现实与人工智能交叉领域的研究与创新

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

【知识点随笔分享 | 第十篇】快速介绍一致性Hash算法

前言&#xff1a; 在分布式系统中&#xff0c;数据的分布和负载均衡是至关重要的问题。一致性哈希算法是一种解决这些挑战的有效工具&#xff0c;它在分布式存储、负载均衡和缓存系统等领域得到了广泛应用。 随着互联网规模的不断扩大&#xff0c;传统的哈希算法在面对大规模…