最大乘法算式-第13届蓝桥杯选拔赛Python真题精选

news2024/12/24 3:15:15

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

最大乘法算式,本题是2022年3月13日举办的第13届蓝桥杯青少组Python编程选拔赛真题编程部分第5题。定一个正整数M和一个数字字符串,使用M个乘号插入到字符串中,请计算并输出最大乘积。

先来看看题目的要求吧。

一.题目说明

编程实现:

给定一个正整数 M(1 ≤ M ≤ 5)和一个只包含数字的字符串(5 < 字符串长度 ≤ 20)。使用M个乘号插入到字符串中,且两个乘号不能相邻,插入后生成一个乘法算式。找出一种使乘法算式数值最大的插入方式,并将结果输出。(乘号不能放在字符串的首尾位置)

如M = 2,字符串为123456,插入2个乘号。插入方式有:

1 * 2 * 3456 = 6912 , 1 * 23 * 456 = 10488 , 1 * 234 * 56 = 13104 , 1 * 2345 * 6 = 14070 ,12 * 3 * 456 = 16416 , 12 * 34 * 56 = 22848 , 12 * 345 * 6 = 24840 , 123 * 4 * 56 = 27552 ,123 * 45 * 6 = 33210,1234 * 5 * 6 = 37020,

其中乘法算式数值最大是第十种,为37020。

输入描述:

第一行输入一个正整数 M(1 ≤ M ≤ 5),表示乘号个数 

第二行输入一个只包含数字的字符串(5 < 字符串长度 ≤ 20),表示要插入M个乘号的字符串

输出描述:

输出一个整数,表示最大乘积数值

样例输入:sd2123456

样例输出:

37020

二.思路分析

这是一道经典的算法题,涉及的知识点包括循环、列表、字符串、枚举算法和动态规划等。

实际上,这是信息奥赛的一道原题,出自2000年NOIP提高组的第二题,原题是这样描述的:

今年是国际数学联盟确定的“2000——世界数学年”,又恰逢我国著名数学家华罗庚先生诞辰 90 周年。在华罗庚先生的家乡江苏金坛,组织了一场别开生面的数学智力竞赛的活动,你的一个好朋友 XZ 也有幸得以参加。

活动中,主持人给所有参加活动的选手出了这样一道题目:设有一个长度为N的数字串,要求选手使用 K个乘号将它分成K + 1个部分,找出一种分法,使得这K+1个部分的乘积能够为最大。

虽然描述有所不同,但意思完全相同,题目还是非常有难度的。

通用的解决方案是使用动态规划,为了让大家更好的理解这个过程,超平老师准备使用3种算法来分析和解读,分别是:

  • 枚举算法

  • 递归算法

  • 动态规划算法

1. 枚举算法

对于编程中出现的大部分算法问题,都可以使用枚举算法来解决,只是效率相对不高。

以题目中的样例数据为例,在字符串"12345"中插入2个乘号,最基础的方法就是将所有的情况列举出来。

这是典型的组合问题,就是在5个位置中任选两个,我们可以使用数学中的”打枪法“,固定一个位置,变换另一个位置。

当第一个✖️在1和2之间时,第二个✖️有4个位置可选,如图:

图片

当第一个✖️在2和3之间时,第二个✖️有3个位置可选,如图:

图片

当第一个✖️在3和4之间时,第二个✖️有2个位置可选,如图:

图片

当第一个✖️在4和5之间时,第二个✖️有1个位置可选,如图:

图片

一共有10种组合,将这10种组合的乘积计算出来,就可以找到最大值37020了。

对于组合问题,在Python编程中,我们可以直接使用combinations()函数,5种组合中任选两个位置,可以使用如下代码:

combinations(range(5), 2)

就可以得到如下10种组合:

(0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)

对于每一种组合,对字符串"123456"进行截取运算,再转成整数,相乘即可。

比如对于组合(0,1),将字符串"123456"拆分成3段,分别为"1"、"2"、"3456",转成整数相乘如下:

1 * 2 * 3456 = 6912

按照同样的方式计算出所有组合的乘积,就可以找到最大值了。

2. 递归算法

枚举算法理解起来比较简单,但是随着字符串长度的增加,时间复杂度会急剧增加,算法效率大大降低,会出现超时情况。

接下来,我们使用递归算法来分析和解决,仍然以字符串s = "123456",M = 2为例进行分析和说明。

首先,我们需要给递归函数下一个明确的定义,这里有两个变量,一个是字符串的长度,一个是乘号的个数。

因此,可以定义f(i, j),表示字符串前i个数字使用j个乘号能够得到的最大乘积。

递归算法的核心思想就是找到f(n)和f(n - 1)之间的关系,也就是最后一步是如何演变过来的。

对于这里定义的f(i, j)来说,需要分析f(i ,j - 1)到f(i ,j)这一步是如何计算的,也就是第前6个数字串中已经有一个✖️了,第二个✖️放在哪儿,可以得到最大值的问题。

由于第二个✖️的位置有多种选择,因此,我们需要分情况讨论。

当第二个✖️在5和6之间时,它表示的是前5个数字串中插入一个✖️的情况,即f(5, 1),如图:

图片

当第二个✖️在4和5之间时,它表示的是前4个数字串中插入一个✖️的情况,即f(4, 1),如图:如图:

图片

当第二个✖️在3和4之间时,它表示的是前3个数字串中插入一个✖️的情况,即f(3, 1),如图:如图:

图片

当第二个✖️在2和3之间时,它表示的是前2个数字串中插入一个✖️的情况,即f(2, 1),如图:如图:

图片

发现这其中的规律了吗?

对于f(6, 2)而言,我们需要分别考虑如下4种情况:​​​​​​​

f(5, 1) * s[5: 6]f(4, 1) * s[4: 6]f(3, 1) * s[3 :6]f(2, 1) * s[2: 6]

然后从这几种情况中,找到最大值即可。

因此,对应f(i, j)而言,其推导公式可以描述如下:​​​​​​​

for k in range(1, i):  f(i, j) = max(f(i, j),f(k, j - 1) * int(s[k:i]))

递归是需要结束条件的,这里的结束条件有两个:

1). j = 0,即没有✖️时,就等于数字串本身,即f(i, j) = int(s[: i]);

2). i <= j时,没办法插入所有✖️,直接返回0。

普通的递归会存在大量的重复计算过程,因此,可以增加一个备忘录,将每一次的计算结果保存起来,从而提升算法效率。

3. 动态规划算法

如果说递归是自顶向下的推导过程,那么动态规划就是自底向上的推导过程,它们都有着共同的推导公式。

使用动态规划算法的要点有如下4个:

  • 定义DP数组

  • 初始化DP数组

  • 状态转移方程

  • 遍历顺序

1). 定义DP数组

根据前面的分析,DP数组可以描述如下:dp[i][j]表示字符串前i个数字中插入j个✖️的最大乘积。

这是一个典型的二维DP数组,对于字符串s = "123456",M = 2来说,我们要计算的是dp[6][2],如图:

图片

所谓的动态规划,其实就是逐步填充表格的过程。

2). 初始化DP数组

根据前面的分析,初始化有两种情况:

  • i <= j时,dp[i][j] = 0;

  • j = 0时,dp[i][j] = int(s[:i]);

对应的二维表格如图所示:

图片

实际上,可以将所有空白单元格中的值初始化为0,后续更新即可。

3). 状态转移方程

和递归算法中的推导公式是一样的,如下:​​​​​​​

for k in range(1, i):  dp(i, j) = max(dp(i, j),dp(k, j - 1) * int(s[k:i]))

这里就不再赘述了。

4). 遍历顺序

遍历顺序很重要,我们逐一来分析。

先从dp[2][1]开始,它表示前2个数字中插入一个✖️的最大乘积,根据上面的状态转移方程,k只能取1,因此:​​​​​​​

dp[2][1] = max(dp[2][1], dp[1][1] * int(s[1:2]))= max(0, 1 * 2)= 2

对应的dp表格如下:

图片

接着是dp[3][1],它表示前3个数字中插入一个✖️的最大乘积,k有两个取值,分别是1和2,需要根据dp[1][0]和dp[2][0]来计算,如下:​​​​​​​

dp[1][0] * int(s[1:3]) = 1 * 23 = 23dp[2][0] * int(s[2:3]) = 12 * 3 = 36

因此,dp[3][1] = 36,如图:

图片

再来计算dp[4][1],它表示前4个数字中插入一个✖️的最大乘积,k有3个取值,分别是1、2和3,需要根据dp[1][0]、dp[2][0]和dp[3][0]来计算,如下:​​​​​​​

dp[1][0] * int(s[1:4]) = 1 * 234 = 234dp[2][0] * int(s[2:4]) = 12 * 34 = 408dp[3][0] * int(s[3:4]) = 12 * 34 = 492

因此,dp[4][1] = 492,如图:

图片

依此类推,可以分别计算dp[5][1]和dp[6][1],结果如下:

图片

同理,计算第3列中的所有单元格,得到最终的二维表格数据,如下:

图片

通过上面的分析过程,相信你已经明白了,这一次,我们要采取先遍历列再变量行的策略,即从左到右,从上到下。

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

三.编程实现

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

  • 枚举算法

  • 递归算法

  • 动态规划

1. 枚举算法

根据前面的思路分析,我们使用combinations()函数获取所有组合,逐个计算乘积,从而获取最大值,代码如下:

图片

代码比较长,说明4点:

1). 首先使用组合函数,获取所有组合,然后对字符串截取,将截取的数字串保存到临时列表temp中,如['1', '2', '3456'];

2). 为方便计算数字串的乘积,定义了一个f()函数,它将temp列表中的数字串依次取出,转成整型,累乘得到成绩,保存到res列表中;

3). res列表保存的是所有乘法算式的乘积,最后使用max()函数获取最大值并输出;

4). 在拆分字符串的时候,需要注意不断地更新和计算起点start和end,同时不要忘了最后一个乘号✖️后面的数字串。

2. 递归算法

使用带备忘录的递归算法,编写代码如下:

图片

代码不算少,说明两点:

1). 为了方便,这里将备忘录列表作为递归的参数进行传递,真正的关键还是i和j这两个参数;

2). 在循环取值的时候,k是从1开始的,确保函数能满足结束条件;

2. 动态规划

根据前面的思路分析,使用动态规划算法,编写代码如下:

图片

代码相对较少,强调两点:

1). 在遍历二维列表的时候,我们始终要遵循i表示行,j表示列的原则,如果要先遍历列,那就先写j,再嵌套i;

2). 对于每一列,起点是从 i + 1开始的,请参考填充DP表格的过程。

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

四.总结与思考

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

  • 循环语句;

  • 列表操作;

  • 枚举算法;

  • 组合函数;

  • 递归算法;

  • 动态规划算法;

作为本次测评的最后一题,难度较大。关键点有两个,一是使用组合函数快速解决问题,二是使用递归思维深入分析计算最大乘积的过程,找到其中的规律,然后选择相应的算法编程实现。

对于本题而言,最基础的方法就是枚举算法,最高效的方法当属动态规划,而递归则是一种讨巧的实现方法。

枚举算法简单粗暴,如果一时半会找不到其他的解决方案,建议可以从枚举算法着手,先确保能解决问题或部分解决问题。

在使用枚举算法解决问题的过程中,说不定灵感就来了,想到更好的方法。实际上,大部分算法都是在枚举的基础上进行优化的。

很多同学都喜欢动态规划,从而忽略了递归算法,我倒是提倡大家多尝试使用递归思维来分析解决问题。

从本质上讲,动态规划和递归算法的核心是一样,但是递归算法的编写难度要小于动态规划,往往会给你带来意想不到的效果。

最后说说动态规划,动态规划的分析过程就是填充表格的过程,所以在解决动态规划问题时,一定要踏踏实实的逐步分析并填充表格,最终的代码往往是比较简单的。

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

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

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

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

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

相关文章

Vue CLI 环境变量使用指南

一、简介 Vue CLI 是一个强大的前端工程化工具&#xff0c;它提供了丰富的配置选项&#xff0c;包括环境变量的管理。环境变量允许开发者根据不同的运行环境&#xff08;如开发、测试和生产&#xff09;应用不同的配置&#xff0c;而无需更改代码。本文将详细介绍如何在 Vue C…

OlSoul系统调校程序v2024.06.05

软件介绍 OlSoul是一款能够适配用于Win各个系统的系统调校软件&#xff0c;OlSoul内置有众多调校功能可以直接使用&#xff0c;如有启用无线网络功能、启用打印机功能、系统快速休眠与休眠开关、快捷方式小箭头去除功能等&#xff0c;具体的调校功能多达几十项&#xff0c;可自…

Python的Pillow(图像处理库)的一些学习笔记

Python的Pillow库是一个非常强大的图像处理库。 安装Pillow库&#xff1a; 在终端或命令行中输入以下命令来安装Pillow&#xff1a; pip install pillow 升级库&#xff1a; pip install pillow --upgrade 一些基础的应用 1、图像文件方面的&#xff1a; 打开文件 …

植物大战僵尸杂交版破解C++实现

文章目录 前言准备工作&#xff1a;基地址与偏移UI界面设计和绑定项目模板总览图生成与实现信号处理1、阳光值更新:BTN12、三种钱币值更新:BTN2-BTN43、冷却刷新:BTN54、锁定阳光&#xff1a;check15、无冷却&#xff1a;check26、OnTimer&#xff08;&#xff09;和OnClose&am…

数 据 类 型

概述 Java 是强类型语言。 每一种数据都定义了明确的数据类型&#xff0c;在内存中分配了不同大小的内存空间&#xff08;字节&#xff09;。 Java 中一共有 8 种基本类型&#xff08;primitive type&#xff09;&#xff0c;包括 4 种整型、2 种浮点型、1 种字符类型&#…

【C语言】07.函数

一、概念 C语言的函数&#xff0c;有些翻译为&#xff1a;子程序&#xff0c;子程序这种翻译更加准确⼀些。 C语言中的函数就是⼀个完成某项特定的任务的⼀小段代码。这段代码是有特殊的写法和调用方法的。 C语言的程序其实是由无数个小的函数组合而成的&#xff0c;也可以说&…

什么是SIEM

SIEM 解决方案是一种企业级应用程序&#xff0c;可集中和自动化与网络安全相关的操作&#xff0c;该工具通过收集、分析和关联从组织 IT 基础设施中的各种实体聚合的网络事件来帮助应对网络威胁。 与帮助监控和评估组织物理空间中的危险的监视控制台相比&#xff0c;SIEM解决方…

【百万字详解Redis】主从复制

文章目录 一、主从复制概述1.1、单机问题1.1.1、机器宕机1.1.2、容器瓶颈1.1.3、QPS瓶颈 1.2、什么是主从复制1.3、主从复制形式1.3.1、一主一从1.3.2、一主多从 1.4、主从复制作用 二、单机主从2.1、复制redis.conf2.2、配置主机2.3、配置从机2.4、启动服务2.5、读写分离 三、…

[工具探索]富士mini90拍立得使用指南

文章目录 1. 基本功能介绍1.1 相机外观1.2 电池与胶片 2. 设置相机2.1 装入电池2.2 装入胶片 3. 拍摄模式3.1 标准模式3.2 儿童模式3.3 远景模式3.4 双重曝光模式3.5 Bulb&#xff08;B&#xff09;模式3.6 **派对模式**3.7 微距模式3.8 **亮度模式**3.9 **定时拍摄模式**3.10 …

php探针代码怎么写

创建php文件并输入代码&#xff0c;访问文件查看php版本、环境和系统配置信息&#xff0c;可使用ini_set()函数定制输出&#xff0c;但注意在生产环境中使用时要注重安全&#xff0c;因为它会泄露敏感信息。 PHP探针代码撰写指南 PHP探针代码是一种脚本&#xff0c;可提供关于…

基于Java Mq的数据交换平台实现_设计消息的格式和内容

基于Java Mq的数据交换平台实现 目录概述需求&#xff1a; 设计思路实现思路分析 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,make a better result,wait for change,challen…

FileZilla:不安全的服务器,不支持 FTP over TLS 原因与解决方法

今天在用FileZilla Client连接某个主机的FTP的时候&#xff0c;主机地址、账号、密码、端口确定百分之百正确的情况下&#xff0c;结果报错如下&#xff1a; 状态: 正在解析 x.x.x 的地址 状态: 正在连接 x.x.x.x:21... 状态: 连接建立&#xff0c;等待欢迎消息... 状态: 不安全…

6.6SSH的运用

ssh远程管理 ssh是一种安全通道协议&#xff0c;用来实现字符界面的远程登录。远程复制&#xff0c;远程文本传输。 ssh对通信双方的数据进行了加密 用户名和密码登录 密钥对认证方式&#xff08;可以实现免密登录&#xff09; ssh 22 网络层 传输层 数据传输的过程中是加密的 …

Java Web学习笔记19——Ajax介绍

Ajax: 概念&#xff1a;Asynchronous JavaScript And XML 异步的JavaScript和XML。 作用&#xff1a; 1&#xff09;数据交换&#xff1a;通过Ajax可以给服务器发送请求&#xff0c;并获得服务器的响应数据。 2&#xff09;异步交互&#xff1a;可以在不重新加载页面的情况…

【NetTopologySuite类库】生成凸包

介绍 计算几何体的凸包。凸包是最小的凸几何体&#xff0c;包含输入几何体中的所有点。使用Graham Scan算法。 API地址&#xff1a; https://nettopologysuite.github.io/NetTopologySuite/api/NetTopologySuite.Algorithm.ConvexHull.html 示意图 示例代码 需在NuGet中安装…

nomachine使用记录以及录包

录包命令&#xff1a; rosbag record 话题名字&#xff08;可以是原相机话题和执行程序的话题&#xff09;rosbag play 包名&#xff08;可以离线播放包的数据&#xff09; rqt_image_view 话题可视化

新买的移动硬盘无法识别

文章目录 背景解决方案 背景 同事新买的移动硬盘&#xff0c;插在电脑上识别不出来盘符&#xff0c;检查了一下&#xff0c;硬盘没问题应该&#xff0c;是ssk的硬盘盒M.2的SSD&#xff0c;硬盘驱动也是正常的&#xff0c;插拔了几次&#xff0c;都不识别&#xff0c;换了太电脑…

未见过类型题每周总结(个人向)

1.DP40 小红取数 题目 解析 一道01背包的衍生问题&#xff0c;我们可以按照它的思路定义数组dp[i][j],表示前i个数中%k为j的最大和。为什么设置未%k的最大和呢&#xff1f;是因为当两个数分别%k&#xff0c;如a%kx&#xff0c;b%ky。那么&#xff08;ab&#xff09;%k&#…

FENDI CLUB精酿啤酒品鉴体验

当提及“品质卓越&#xff0c;口感非凡”的啤酒时&#xff0c;FENDI CLUB精酿啤酒无疑是一个值得一试的选择。这款啤酒以其独特的酿造工艺和优质的原料&#xff0c;为消费者带来了与众不同的味觉享受。 一、独特的酿造工艺 FENDI CLUB精酿啤酒在酿造过程中&#xff0c;严格遵循…

关于 spring boot 的 目录详解 和 配置文件 以及 日志

目录 配置文件 spring boot 的配置文件有两种格式&#xff0c;分别是 properties 和 yml&#xff08;yaml&#xff09;。这两种格式的配置文件是可以同时存在的&#xff0c;此时会以 properties 的文件为主&#xff0c;但一般都是使用同一种格式的。 格式 properties 语法格…