扎气球最高分-第13届蓝桥杯选拔赛Python真题精选

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

扎气球最高分,本题是2021年11月27日举办的第13届蓝桥杯青少组Python编程选拔赛真题编程部分第5题。题目要求对于给定的n个排成一排的气球,将所有气球扎破能够得到的最高分数。

先来看看题目的要求吧。

一.题目说明

编程实现:

小明去游乐场玩飞镖扎气球的游戏,一共有n个气球,依次排成一行,每个气球上有一个数字,表示这个气球的分值。

游戏计分规则:

1、戳破1个气球,将获得其本身及左右相邻气球,共三个分值相乘的分数;

2、如果戳破的气球左边或右边没有气球,则获得其本身及相邻气球,共两个分值相乘的分数;如果被戳破的气球左边和右边都没有气球(是最后一个被戳破的气球),则这个气球本身的分值作为分数;

3、已经被戳破的气球不再计算。

飞镖数量不限,可以任意选择顺序戳破气球,根据计分规则,争取使得游戏最后得分最高。

例如:一共有3个气球,分值分别为2,4,6。

若想获得最高得分:

1). 先戳破4,得分为2 x 4 x 6 = 48;

2). 再戳破2,得分为2 x 6 = 12,累计得分60;

3). 再戳破6,得分为6,累计得分66;

最后总得分为66,为最高得分。

输入描述:

输入n个正整数,表示气球的分值,且正整数之间以一个英文逗号隔开

输出描述:

输出正整数,表示戳破所有气球后获得的最高得分

样例输入:

2,4,6

样例输出:

66

二.思路分析

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

这是一个求最值问题,对于最值问题,常见的实现方案有枚举算法、贪心算法、递归算法、回溯算法和动态规划等。

那么你知道本题属于哪种类型呢?

实际上,这是典型的区间DP问题,区间DP问题通常涉及一个列表或数组,需要对其某些子区间进行操作,并通过这些操作的结果来求解整个列表或数组的某些性质或最优值。

区间DP的基本思想是通过定义二维的DP状态数组dp[i][j],表示从序列的第i个元素到第j个元素(即区间[i, j]的最优解,例如最小/最大的某个值)。然后,通过考虑如何将大区间分解成较小的区间,并利用这些较小区间的最优解来构造大区间的最优解,来进行状态转移。

对于动态规划问题,核心点有如下4个:

  • 定义dp数组

  • 初始状态

  • 状态转移方程

  • 遍历顺序

接下来,我们逐一分析这4个核心要素。

1. 定义dp数组

由于这是一个区间DP问题,因此dp数组是一个二维列表,即dp[i][j],表示扎破从i到j之间所有的气球的最高得分。

此时,有一个问题需要明确,这里的i和j是否也包含呢?

我们看一组实际的数据,假设有4个气球,分值为3, 2, 4, 6,如图:

图片

在计算最高分的时候,还需要考虑气球是否处于最左边和最右边,代码比较繁琐。

可以考虑在左右两边增加两个虚拟气球,其分值为1,如图:

图片

如此一来,所有的黄色气球都处于中间位置,再也不需要考虑边界问题了。

当然,这也让我们进一步明确了dp[i][j]的含义,它表示的是扎破i到j之间所有气球的最高得分。

对于上面的4个气球来说,最后的结果是dp[0][5],表示从0~5之间所有的气球,不包括0和5本身,因为这两个气球是虚拟的,根本不存在。

可以绘制表格如下:

图片

最右上角的单元格dp[0][5]就是最终要计算的结果,实际上,所谓的动态规划,其实就是一个填表的过程。

2. 初始状态

所谓初始状态就是最简单的情况,对于戳气球问题而言,最简单的情况就是没有气球,此时得分为0。

对应到dp[i][j]数组,就是当j - i <= 1,即i和j两者之间没有气球可扎了,当然也就没有分数了。

对应的dp表格如下:

图片

这里将处在对角线偏右上的单元格设置为0,即:

dp[0][1] = dp[1][2] = dp[2][3] = dp[3][4] = dp[4][5]= 0

对于dp表格,我们要计算的是右上方的单元格,左下方的单元格可以忽略不计。

3. 状态转移方程

对于动态规划问题,状态转移方程是重点,也是难点,这里的状态转移方程又该如何确定呢?

还是以上面的数据为例,我们只需要分析最后戳破哪个气球的过程,4只气球可以分四种情况来考虑。

1). 最后戳第一只气球

最后戳破的气球分值为3,如图所示:

图片

这相当于把dp[0][5]拆分成两个子区间,分别是dp[0][1]和dp[1][5],戳破当前气球的得分为1 * 3 * 1,所以:

dp[0][5]= dp[0][1] + dp[1][5] + 3

2). 最后戳第二只气球

最后戳破的气球分值为2,如图所示:

图片

这相当于把dp[0][5]拆分成两个子区间,分别是dp[0][2]和dp[2][5],戳破当前气球的得分为1 * 2 * 1,所以:

dp[0][5]= dp[0][2] + dp[2][5] + 2

3). 最后戳第三只气球

最后戳破的气球分值为4,如图所示:

图片

这相当于把dp[0][5]拆分成两个子区间,分别是dp[0][3]和dp[3][5],戳破当前气球的得分为1 * 4 * 1,所以:

dp[0][5]= dp[0][3] + dp[3][5] + 4

4). 最后戳第四只气球

最后戳破的气球分值为6,如图所示:

图片

这相当于把dp[0][5]拆分成两个子区间,分别是dp[0][4]和dp[4][5],戳破当前气球的得分为1 * 6 * 1,所以:

dp[0][5]= dp[0][4] + dp[4][5] + 6

到底哪一种情况得分最高呢,其实就是取最大值的问题了。

你看到这其中的规律了吗?

实际上就是在i和j之间找分割点k,将dp[i][j]拆分成两个子区间dp[i][k]和dp[k][j],如图所示:

图片

对于每个分割点来说,左边区间的最大分值是dp[i][k],右边区间的最大分值是dp[k][j],加上本次戳破气球的分数p[i] * p[k] * p[j],这里的列表p保存的是每个气球的分值,包括左右两端的虚拟气球。

因此,状态转移方程如下:

dp[i][j] = max(  dp[i][j],   dp[i][k] + dp[k][j] + p[i] * p[j] * p[k])

这意味着,我们需要使用循环枚举i到j之间的每个分割点k,计算其最大分值,然后将最大值作为dp[i][j]的结果。

4. 遍历顺序

对于二维列表dp[i][j]来说,常见的遍历顺序是从上到下,从左到右。但是对于区间DP来说,不能采取这种遍历顺序。

我们还是看图说话吧,以计算dp[2][5]为例,它的分割点k有两个。

当k = 3时,计算如下:

dp[2][5] = dp[2][3] + dp[3][5] + p[2]* p[3] * p[5]

对应的DP表格如图:

图片

当k= 4时,计算如下:

dp[2][5] = dp[2][4] + dp[4][5] + p[2]* p[4] * p[5]

对应的DP表格如图:

图片

相信你已经发现了,在计算dp[2][5]的时候,它可以通过dp[2][3] + dp[3][5]计算出来,也可以通过dp[2][4] + dp[4][5]计算出来。

很显然,dp[2][3]、dp[3][5]、dp[2][4]、dp[4][5]这些单元格都在dp[2][5]的左方和下方,这就意味着不能使用传统的从上到下、从左到右。

针对这种情况,我们可以有两种遍历方式,一是斜线遍历,如图:

图片

二是从下到上,从左到右,如图:

图片

相对来说,使用第二种遍历方式更为简单一些。

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

三.编程实现

根据上面的思路分析,我们编写程序如下:

图片

代码不多,说明4点:

1). pts表示输入的气球分值,左右各增加了一个分值为1的气球,这里直接使用列表相加的运算,非常方便;

2). 二维dp列表行和列都是n + 2,初始值为0,这里使用了列表推导式;

3). i表示行,从下到上,初始值是n -1,终点是0,j表示列,自左至右,初始值是i  + 1,终点是n + 1;

4). k表示分割点,起始值是k+1,终点是j - 1。

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

四.总结与思考

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

  • 循环语句,尤其是嵌套循环;

  • 列表的操作;

  • 动态规划算法;

作为本次测评的最后一题,代码虽然不多,但是难度较大。关键点有两个,一是理解区间DP的算法思想,二是彻底弄清填充DP表格的方法和过程。

估计你已经发现了,最终的代码并不多,难的是过程分析,动态规划说难也难,说简单也简单。

动态规划说白了,就是根据题目意思定义一个表格,可能是一维的,也可能是二维的,然后找到规律,也就是状态转移方程,不断地计算并填充每一个单元格。

因此,在学习动态规划算法的时候,一定要亲自动手绘制并填充表格,这个过程会有些繁琐,但是效果非常好,写代码反倒是最简单的事情了。

超平老师给你留两道思考题:

1). 如何使用递归算法,计算最大分值?

2). 如果使用斜线遍历的顺序,代码又该怎么写呢?

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

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

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

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

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

相关文章

Spring框架温习

Spring Spring是一个全面的、企业应用开发一站式的解决方案&#xff0c;贯穿表现层、业务层、持久层。但是 Spring仍然可以和其他的框架无缝整合。 Spring 特点&#xff1a; 轻量级、控制反转、面向切面、容器、框架集合 Spring 核心组件&#xff1a; Spring 常用模块&…

【Redis】 关于 Redis 有序集合类型

文章目录 &#x1f343;前言&#x1f334;普通命令介绍&#x1f6a9;zadd&#x1f6a9;zcard&#x1f6a9;zcount&#x1f6a9;zrange&#x1f6a9;zrevrange&#x1f6a9;zrangebyscore&#x1f6a9;zpopmax&#x1f6a9;zpopmin&#x1f6a9;zrank&#x1f6a9;zrevrank&…

Shell脚本的分支语句,循环语句

分支语句 if 表达式 then 命令表 fi 如果表达式为真&#xff0c;则执行命令表中的命令&#xff0c;否则退出。执行fi后的语句。 给文件权限:chmod 0777 文件名 输出: ./文件名 grep 查找用户名&#xff0c;管道wc -l 统计字符 2.多路分支语句 记得给文件名权限喔&#x…

OSPF扩展知识2

FA-转发地址 正常 OSPF 区域收到的 5 类 LSA 不存在 FA 值&#xff1b; 产生 FA 的条件: 1、5类LSA ----假设 R2为 ASBR&#xff0c;90/0 口工作的 OSPF 中&#xff0c;g0/1 口工作在非 ospf 协议或不同 ospf 进程中&#xff1b;若 g0/1 也同时宣告在和 g0/0 相同的 OSPF 进程…

R语言入门 | 使用 ggplot2 进行数据可视化

1.0准备工作 先下好tidyverse包&#xff0c;并进行加载。 install.packages ( "tidyverse" ) library(tidyverse) R 包只需安装一次&#xff0c;但每次开始新会话时都要重新加载。 1.1 数据框 数据框是变量&#xff08;列&#xff09;和观测&#xff08;行&#x…

算法练习——字符串

一确定字符串是否包含唯一字符 1.1涉及知识点 c的输入输出语法 cin>>s; cout<<"NO"; 如何定义字符串 切记&#xff1a;在[]中必须加数字——字符串最大长度&#xff0c;不然编译不通过 char s[101]; 如何获取字符串长度 char s[101];cin>>s;i…

windows10远程桌面端口,修改Windows 10远程桌面端口的步骤

在Windows 10操作系统中&#xff0c;远程桌面功能为企业用户、技术支持人员以及个人用户提供了极大的便利&#xff0c;允许他们远程访问和管理另一台计算机的桌面环境。然而&#xff0c;默认的远程桌面端口&#xff08;通常为3389&#xff09;常常成为安全漏洞的潜在目标&#…

【图像处理与机器视觉】图像处理概述与像素

什么是数字图像处理 改善图像信息&#xff0c;便于作出解释 方便对图像传输&#xff0c;储存&#xff0c;方便机器理解 什么是数字图像 &#xff08;1&#xff09;模拟图像&#xff1a;连续二维函数 f&#xff08;x&#xff0c;y&#xff09;表示&#xff0c;其中 x&#xf…

操作系统真象还原:一些你可能正感到迷惑的问题

第0章-一些你可能正感到迷惑的问题 这是我看操作系统真象还原这本书的一些记录&#xff1a; 4 软件是如何访问硬件的 硬件在输入输出上大体分为串行和并行&#xff0c;相应的接口也就是串行接口和并行接口。串行硬件通过串行接口与 CPU 通信&#xff0c;反过来也是&#xff…

【uni-app】Pinia 持久化

小程序端 Pinia 持久化 说明&#xff1a;Pinia 用法与 Vue3 项目完全一致&#xff0c;uni-app 项目仅需解决持久化插件兼容性问题。 持久化存储插件 安装持久化存储插件&#xff1a; pinia-plugin-persistedstate pnpm i pinia-plugin-persistedstate插件默认使用 localStor…

MySQL——JDBC编程

目录 前言 一、JDBC概述 二、准备工作 1.下载MySQL的JDBC驱动包 2.把jar引入到项目中 三、JDBC编程 1.插入操作 2.查询操作 尾声 前言 本篇文章主要介绍如何利用Java代码进行操作数据库&#xff0c;在实际开发中&#xff0c;绝大多数对数据库的操作我们都是通过代码进行…

uni-app全局弹窗的实现方案

背景 为了解决uni-app 任意位置出现弹窗 解决方案 一、最初方案 受限于uni-app 调用组件需要每个页面都引入注册才可以使用&#xff0c;此方案繁琐&#xff0c;每个页面都要写侵入性比较强 二、改进方案 app端&#xff1a;新建一个页面进行跳转&#xff0c;可以实现伪弹窗…

筛选的艺术:数组元素的精确提取

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、筛选的基本概念 二、筛选的实际应用案例 1. 筛选能被三整除的元素 2. 筛选小于特定值…

C++ list类

目录 0.前言 1.list介绍 1.1优势 1.2劣势 1.3容器属性 2.list使用 2.1构造函数 2.1.1默认构造函数 2.1.2填充构造函数 2.1.3范围构造函数 2.1.4拷贝构造函数 2.1.5初始化列表构造函数 2.2迭代器 2.2.1 begin() 2.2.2 end() 2.2.3 cbegin() 2.2.4 cend() 2.2.…

PyMySQL连接池

背景 在用python写后端服务时候&#xff0c;需要与mysql数据库进行一些数据查询或者插入更新等操作。启动服务后接口运行一切正常&#xff0c; 隔了第二天去看服务日志就会报错&#xff0c;问题如下&#xff1a; pymysql.err.OperationalError: (2006, "MySQL server ha…

JavaScript-内存分配

内存空间 内存分为栈和堆 栈&#xff1a;由操作系统自动释放存放的变量值和函数值等。简单数据类型存放在栈中 栈会由低到高先入后出 堆&#xff1a;存储引用类型 &#xff08;对象&#xff09; 对象会先将数据存放在堆里面&#xff0c;堆的地址放在栈里面

数字孪生智慧车站:全方位可视化管理平台

运用图扑数字孪生技术&#xff0c;智慧车站可视化管理平台实时模拟并监控车站运行状态&#xff0c;通过整合即时数据与历史数据&#xff0c;提供精准分析和预测。该平台支持乘客流量管理、设备运行监控、安全预警等多项功能&#xff0c;提高车站运营效率与安全性。直观的可视化…

这个橙子真的香!老司机徒手把玩香橙派Kunpeng Pro事后回忆录

说&#xff01;你是哪个门派&#xff1f; 香橙&#xff0c;芸香科柑橘属小乔木。枝通常有粗长刺&#xff0c;新梢及嫩叶柄常被疏短毛。叶厚纸质&#xff0c;翼叶倒卵状椭圆形&#xff0c;顶部圆或钝。。。 咦&#xff1f;小李&#xff1f;我们不是搞IT的嘛&#xff0c;怎么会有…

(函数)求一元二次方程的根(C语言)

一、运行结果&#xff1b; 二、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h> # include <math.h>//声明函数&#xff1b; //判断条件等于0时&#xff1b; void zeor(double a, double b);//判断条件大于0时&#xff1b; void bigzeo…

浅谈 parallelStream和Stream 源码及其应用场景

上篇讲述了list.forEach()和list.stream().forEach() 异同点 谈到了并行流的概念&#xff0c;本篇则从源码出发&#xff0c;了解一下其原理。 一、流的初始操作流程 jdk8中 将Collection中加入了转换流的概念。 default Stream<E> stream() {return StreamSupport.str…