密室逃脱游戏-第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.mzph.cn/diannao/7524.shtml

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

相关文章

idea Maven 插件 项目多环境打包配置

背景 不同环境的配置文件不一样&#xff0c;打包方式也有差异 1. 准备配置文件 这里 local 为本地开发环境 可改为 dev 名称自定义 test 为测试环境 prod 为生产环境 根据项目业务自行定义 application.yml 配置&#xff1a; spring:profiles:#对应pom中的配置active: spring.…

3月10日PMP考试成绩已出!教你如何快速查询

3月10日PMP考试终于出成绩啦&#xff01; 2024年3月10日PMP考试成绩正在陆续分批次发布&#xff0c;预计本周成绩会全部出来&#xff0c;目前已经有同学查询到自己的成绩&#xff0c;暂时没查到成绩的同学请耐心等待。 在等待成绩的同时&#xff0c;大家可以先对PMP证书和成绩…

CST电磁仿真软件远场源的导出调用和提取结果【小白必看】

远场源的导出&调用(1) 提取Hybrid仿真所需的远场源&#xff01; Post-Processing > Tools > Result Templates Tools >Farfield and Antenna Properties > Export Farfields As Source 混合求解(Hybrid Simulation)是对安装在舰船等大型平台上的天线进行仿真…

为什么会查询不到DNS信息?怎么排查?

DNS&#xff08;域名系统&#xff09;是将域名转换为相应 IP 地址的关键系统。查询 DNS 信息具有重要作用&#xff0c;通过查询 DNS 信息&#xff0c;我们可以知道域名对应的 IP 地址&#xff0c;这是最主要的信息&#xff0c;使设备能与目标服务器进行通信&#xff1b;其次是域…

IPO压力应变桥信号处理系列隔离放大器 差分信号隔离转换0-10mV/0-20mV/0-±10mV/0-±20mV转4-20mA/0-5V/0-10V

概述&#xff1a; IPO压力应变桥信号处理系列隔离放大器是一种将差分输入信号隔离放大、转换成按比例输出的直流信号混合集成厚模电路。产品广泛应用在电力、远程监控、仪器仪表、医疗设备、工业自控等行业。该模块内部嵌入了一个高效微功率的电源&#xff0c;向输入端和输出端…

快速了解OV证书和DV证书的区别及使用场景

OV&#xff08;Organization Validation&#xff0c;组织验证&#xff09;证书和DV&#xff08;Domain Validation&#xff0c;域名验证&#xff09;证书都是SSL/TLS证书&#xff0c;用于保护网站数据传输的安全性和提供身份验证&#xff0c;但两者在验证深度、信任级别、提供的…

【Java EE】多线程(三)线程状态

&#x1f4da;博客主页&#xff1a;爱敲代码的小杨. ✨专栏&#xff1a;《Java SE语法》 | 《数据结构与算法》 | 《C生万物》 |《MySQL探索之旅》 |《Web世界探险家》 ❤️感谢大家点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;&#xff0c;您的三连就是我持续更…

Spring AOP(3)

目录 Spring AOP原理 代理模式 代理模式中的主要角色 静态代理 动态代理 总结:面试题 什么是AOP? Spring AOP实现的方式有哪些? Spring AOP实现原理 Spring使用的是哪种代理方式? JDK和CGLIB动态代理的区别? Spring AOP原理 代理模式 代理模式, 也叫委托模式. …

JavaScript 流程控制语句详解:if语句、switch语句、while循环、for循环等

JavaScript&#xff0c;作为一种广泛使用的编程语言&#xff0c;它的流程控制语句是构建逻辑和实现功能的基础。流程控制语句包括条件语句、循环语句和转向语句&#xff0c;它们是编程中不可或缺的部分。 接下来&#xff0c;我们将一一解析这些语句&#xff0c;带你走进JavaSc…

刷代码随想录有感(58):二叉树的最近公共祖先

题干&#xff1a; 代码&#xff1a; class Solution { public:TreeNode* traversal(TreeNode* root, TreeNode* p, TreeNode* q){if(root NULL)return NULL;if(root p || root q)return root;TreeNode* left traversal(root->left, p, q);TreeNode* right traversal(r…

NVIDIA Omniverse Cloud API支持数字孪生开发,可解决复杂AI问题 | 最新快讯

在全球范围内&#xff0c;价值超过 50 万亿美元的重工业市场&#xff0c;正在竞相实现数字化。 基于此&#xff0c;为帮助数字孪生技术更好地赋能千行百业&#xff0c;AI 企业 NVIDIA 在架构底层算力的同时&#xff0c;也搭建了 NVIDIA AI Enterprise 和 Omniverse 两大平台。 …

【UGUI】实现长按播放动画松手停止动画播放

场景部分&#xff0c;需要把角色和动画组件、动画控制器、动画片段准备好 然后设置好转换动画的参数RUN (bool类型的) 创建一个普通按钮在UGUI里面&#xff0c;为按钮添加组件EventTrgger 在这个组件里面添加PointerDown 和PointerUp 这两个分别代表按下和弹起&#xff01; 他…

【Python小技巧】matplotlib不显示图像竟是numpy惹的祸

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、问题&#xff1a;df.plot() 显示不出图像二、尝试各种解决办法1. 增加matplotlib.use&#xff0c;设定GUI2. 升级matplotlib版本 三、numpy是个重要的库1. …

如何永久删除服务和相关文件夹

如何永久删除服务和文件夹&#xff1f; How can I remove the service and folder permanently? 以AlibabaProtect服务为例 takeown /f "C:\Program Files (x86)\AlibabaProtect sc delete AlibabaProtect我运行了上述操作&#xff0c;并通过任务管理器杀死了“阿里巴巴…

HTML5+CSS3+JS小实例:旋转渐变光标

实例:旋转渐变光标 技术栈:HTML+CSS+JS 效果: 源码: 【HTML】 <!DOCTYPE html> <html lang="zh-CN"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale…

python学习笔记-01

python 在学习之前要了解的事项&#xff1a; 1.python缩进语法要求较为严格 2.是解释型语言 3.python2版本和python3版本不兼容 本系列笔记全部基于python3 1.hello world 安装好python之后&#xff0c;可以直接打开python&#xff0c;也可以通过cmd进入python。 print(&qu…

LineVul实验复现及相关问题

最近在复现 LineVul 这篇文章的实验&#xff0c;本文主要用于简化文章复现流程和记录复现过程中出现的问题。 1 安装依赖环境 pip install gdown pip install transformers pip install captum pip install torch torchvision torchaudio pip install numpy pip install tqdm…

实用工具radsystems,十分钟完成项目的登入注册,增删改查

发了这么多文章&#xff0c;很多人不知道这些文章是在讲什么&#xff0c;今天我来介绍一下逆天神器radsystems radsystems是一个可以快速开发的软件&#xff0c;也可以二次开发&#xff08;之前文章有讲&#xff09; 它可以帮助我们快速完成开发&#xff0c;毫不夸张的讲&…

探秘Flex布局下子元素宽度超出的那些烦心事

嘿&#xff0c;小伙伴们&#xff01;你们有没有遇到过用Flex布局的时候&#xff0c;子元素的宽度莫名其妙地超出了父元素的情况&#xff1f;别着急&#xff0c;今天我就来给大家揭秘这个问题的来龙去脉&#xff0c;以及一些解决方案。让我们一起来深入探讨&#xff01; 发现问…

自然语言处理: RAT = CoT + RAG

Retrieval Augmented Thoughts (RAT) 是一种协同思维链 (CoT) 和检索增强生成 (RAG) 的 AI 提示策略&#xff0c;助力解决具有挑战性的长任务推理和生成。 RAG 有关于RAG的介绍可以参考我之前的博文: 自然语言处理: 第十五章RAG(Retrieval Augmented Generation) 开发能够像人…