使用动态规划解决分钱方案-2023年全国青少年信息素养大赛Python复赛真题精选

2023-10-27

 [导读]:超平老师计划推出《全国青少年信息素养大赛Python编程真题解析》50讲,这是超平老师解读Python编程挑战赛真题系列的第14讲。

全国青少年信息素养大赛(原全国青少年电子信息智能创新大赛)是“世界机器人大会青少年机器人设计与信息素养大赛”赛事之一,由中国电子学会主办,包含很多赛项,大赛自2013年举办,已连续成功举办八届,已正式入围“2022-2025学年面向中小学生的全国性竞赛活动名单”。 

大赛旨在激发广大青少年的科学兴趣和想象力,培养钻研探究、创新创造的科学精神和实践能力,促进青少年科技创新活动的广泛开展,发现和培养一批具有科研潜质和创新精神的青少年科技创新后备人才。

大赛主要竞赛类别包括电子科技、智能机器人、软件编程三类,全国青少年Python编程挑战赛就属于其中的软件编程类。

一.赛事说明

2023年(第9届)Python挑战赛赛程分为初赛、复赛和总决赛三个阶段。初赛是资格赛,复赛是地方选拔赛,总决赛是全国各地选拔的精英汇聚在一起进行PK。

本届Python挑战赛是在线上举行,参赛选手登录大赛官网在指定页面完成答题并提交答案。评定成绩的依据是同时考虑得分和用时两个方面,首先是得分高者名次靠前,如果得分一样,则用时少者名次靠前。

2023年全国青少年Python编程挑战赛华北赛区(北京)初中组复赛于2023年7月15日正式举行。一共有6道题,全是编程题,考试时间是90分钟。

今天超平老师分享的是第5题,分钱方案。

二.题目说明

题目背景:

有n个人,他们需要分配m元钱 (m >= n),每个人至少分到1元钱,且每个人分到的钱数必须是整数。

请问有多少种分配方案?

输入描述:

输入一行两个正整数n, m,用空格间隔。

输出描述:

输出分配方案数。

样例1:

输入:

5  10

输出:

126

三.思路分析

从本题的描述来看,这是一个排列组合问题,但并不是简单地从m个元素中直接选取n的简单组合问题。

我们可以换个说法,这相当于将m个球放入n个盒子中,每个盒子至少有一个球的问题。

图片

针对这类问题,我们首先能想到的就是枚举算法,但是这里的m和n不是固定的数字,无法确定循环嵌套的层数,所以枚举算法是行不通的。

对于不确定次数的枚举算法,可以尝试使用递归算法来解决。递归的关键是要找到推导公式和出口条件,重点是推导公式,也就是第n项和第n-1项之间的关系。

我们使用f(m, n)来表示m个球放到n个盒子里(每个盒子里至少一个小球)的方案数量,然后来分析第n个盒子和前n - 1和盒子之间的关系。

  • 如果第n个盒子放1个小球,那么前面n - 1个盒子要存放 m - 1个小球,即f(m - 1, n -1);

  • 如果第n个盒子放2个小球,那么前面n - 1个盒子要存放 m - 2个小球,即f(m - 2, n -1);

  • 如果第n个盒子放3个小球,那么前面n - 3个盒子要存放 m - 1个小球,即f(m - 3, n -1);

  • ......

  • 如果第n个盒子放i个小球,那么前面n - i个盒子要存放 m - i个小球,即f(m - i, n -1);

请你思考一下,第n个盒子最多可以放几个小球呢?

由于要确保每个盒子至少1个小球,所以第n个盒子最少放1个小球,最多放m - n + 1个小球。因为前面的每个盒子装1个小球,一共要装 n - 1个小球,然后用总数m减去 n - 1,就是 m - n + 1个小球了。

再将所有的方案加起来就可以得到总的方案数量了,即:

图片

那么递归的出口条件呢,这个比较简单,就是只有一个人的时候,即n = 1,此时只有一种方案。

递归算法理解起来相对要简单一些,代码也比较简洁,但是它有一个严重的问题,就是当m和n比较大的时候,程序运行时间比较长,有可能会超出题目的时间要求。

所以,我们还需要优化我们的程序,大多数情况下,能用递归解决的问题,可以使用动态规划(DP)算法来解决,这才是本题最优的解决方案,关于动态规划的思路分析,我们稍后再讲。

接下来,我们进入具体的编程实现环节。

四.编程实现

根据上面的思路分析,我们使用两种方式来编写代码:

  • 递归算法

  • 动态规划

1.递归算法

根据前面的思路分析和递归算法的实现方式,需要先定义好递归函数,代码如下:

图片

这里增加了一个m < n的判断,此时无法分钱,所以返回0。

有了该函数,主代码就比较简单了,如下:

图片

简单说明三点:

1). split函数的作用是通过指定分隔符对字符串进行切片,并返回分割后的字符串列表,默认的分隔符是空格;

2). 使用split函数切片后得到的字符串,需要转换成整数,所以这里使用了int函数;

3). 这里使用了列表推导式,这是一个非常有用的技巧,一定要熟练掌握。

递归的好处就是理解起来简单,缺点就是当递归层数较多时,执行时间太长,考试时有可能出现超时的情况。

2.动态规划

动态规划,英文Dynamic Programming,简称DP,如果某一问题有很多重叠子问题,使用动态规划是最有效的。

图片

在递归算法中,我们是从后往前,即从n到n - 1、从n - 1到n - 2...,直到1结束。而动态规划中每一个状态一定是由上一个状态推导出来的,它是从前到后的。

对于动态规划,通常可以分成如下5个步骤:

  • 确定dp数组以及下标的含义

  • 确定递推公式

  • dp数组如何初始化

  • 确定遍历顺序

  • 举例推导dp数组

首先dp数组,在本题中,dp是一个二维数组,dp[i][j]表示将j个小球放到i个盒子里的方案数量。

只看这个二维数组的定义,可能会有点懵,还是看图吧:

图片

时刻牢记,dp[i][j]表示将j个小球放到i个盒子里的方案数量,很显然,在如下3种情况下,方案数量都为0:

1). i = 0时,表示没有盒子,方案数为0;

2). j = 0时,表示小球数量为0,方案数为0;

3). i > j 时,不能满足每个盒子都装一个小球,方案数为0;

当 i = 1时,也就是只有一个盒子时,方案数量为1,如图:

图片

这里的难点是确定递推公式,根据前面递归算法中的思路分析,有如下公式:

图片

其中,i - 1表示是上一行,j的值从i - 1开始直到 j - 1结束,这就意味着dp[i][j]等于上一行从第i - 1列到第j-1列所有格子的总和。

按照这个思路,可以将上面的表格填写完整,如图:

图片

为了你更好地理解,我举例说明如下:

图片

聪明的你也许已经发现了,上面的递推公式可以简化为:

图片

此处有点烧脑,你要好好理解一下,既然dp[i][j]等于上一行左边所有列的和(由于最左边的都为0,可以直接累加进来),那么dp[i][j - 1]就等于它上一行左边所有列的和(不包括第j - 1列),所以二者相加就刚好等于dp[i][j]了。

根据上面的分析,初始化也就比较简单了,首先初始化一个n + 1行m + 1列的二维列表,每一项元素的值都设置为0,然后将第2行(下标为1)的值设置为1。

从第3行(下标为2)开始,使用递推公式计算出每一个列表项的值即可,遍历顺序按照先行后列即可。

完整的代码如图所示:

图片

输入数据进行测试,即使n和m的值都非常大,也可以很快地输出结果,非常完美,这才是解决本题的最佳方案。

五.总结与思考

本题难度较大,考查的知识点主要包括:

  • 处理输入数据;

  • 列表推导式

  • 二维列表;

  • 递归算法;

  • 动态规划;

作为初中组复赛倒数第二题,本题还是非常有难度的,已经上升到常用算法层面了,而且还是有点难度的动态规划算法。

如果你想从比赛中脱颖而出,算法学习是必不可少的。相对来说,递归是一种简单的算法,但是递归也存在弊端,就是当递归的层数不断增加之后,程序的执行时间会急剧增加。

大部分递归算法问题,都可以使用动态规划来解决,对于动态规划算法来说,其核心在于dp数组的理解及递推公式的确定,这个需要经过大量的练习才能熟练掌握。

给你留一个小小的思考题,根据动态规划算法中的递推公式,你能否将递归算法中的代码进行简化呢?

你还有什么巧妙的解决方案吗,欢迎和超平老师交流。

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用动态规划解决分钱方案-2023年全国青少年信息素养大赛Python复赛真题精选 的相关文章

随机推荐

  • 【DockerCE】使用docker配置和运行HertzBeat

    HertzBeat是一款免Agent的监控平台 拥有强大自定义监控能力 可以对应用服务 中间件 数据库 操作系统 云原生等进行监控 配置监控告警阈值 以及告警通知 邮件 微信 钉钉 飞书 关于这个软件的介绍 我这里就不做过多的介绍了 感兴趣
  • (二)代码好坏判定

    好坏只是笼统的判定 好代码 易扩展 易读 简单 易维护 判断代码的角度 灵活性 flexibility 可扩展性 extensibility 可维护性 maintainability 可读性 readability 可理解性 underst
  • Linux多进程编程

    fork系统调用 include
  • scrapy爬虫的搭建过程(实战篇)

    scrapy爬虫的搭建过程 实战篇 1 爬虫功能 以 http bbs fengniao com forum forum 125 1 lastpost html 为起始页 爬取前十页的信息 包括文章的标题 链接地址和图片地址 保存到mong
  • 超详细!基于Proteus的简易测频计实现(数字电路课程设计)

    本文阐述基于Proteus 7 8的简易测频计电路的实现 附具体电路的工程文件下载 工程文件下载链接 设计要求 闸门时间1S 10S可选 读数保持时间10秒 可选 四位数字显示 范围000 1 9999 Hz 能够自动进行下一次测量 设计方
  • 关于null的typeof和instanceof

    问题 alert typeof null object alert null instanceof Object false 答案 这是由Javascript规范规定的 Null和Object都是javascript中的数据类型 Null数
  • DC靶机系列:DC-3

    一 信息收集 查询本机ip及目标靶机ip 本机ip 192 168 56 104 利用nmap查询同网段存活的ip 或者使用arp scan l 靶机ip为 192 168 56 112 下一步收集靶机开放的端口信息 收集靶机开放端口 输入
  • Springboot解决跨域问题的配置

    由于自己是主后端开发 前端自己很少去配置 所以自己留一个配置SpringBoot配置跨域问题的代码在这里 注意一点 如果是在生产环境 应该根据实际需求设置allowedOrigins来限制允许访问的域名 而不是使用通配符 import or
  • nvidia 显卡硬件文档手册

    https github com NVIDIA open gpu doc
  • vue项目控制按钮是否显示

    import Vue from vue permission 用于控制是否显示按键 控制权限的指令 Vue directive has bind function el binding if Vue
  • 批量将markdown内本地图片转换为网络图片

    批量将markdown内本地图片转换为网络图片 在线地址 http 106 52 170 128 8003 需求 大部分支持markdown格式的网站 都不支持将markdown和其内置的图片同时上传到服务器 因此增大了小朋友们写文档的负担
  • 软件开发中几个常用功能的实现

    软件开发中几个常用功能的实现 出处 vchelp net责任编辑 leelee 04 8 12 10 01 作者 戚高 在进行软件开发过程中间 有很多小功能的实现 虽然这些东西你可以不用 但是如果应用仂将会是你的程序更具有专业性 一 设置程
  • Unity 3D 动画系统(Mecanim)

    Unity 3D 动画系统 Mecanim Mecanim 动画系统是 Unity 公司推出的全新动画系统 具有重定向 可融合等诸多新特性 可以帮助程序设计人员通过和美工人员的配合快速设计出角色动画 其主界面如下图所示 Unity 公司计划
  • 小写的bool和大写BOOL

    bool是标准C 中的布尔量 占一个字节大小内存 只有false或者true 具有跨平台特性 BOOL是MFC定义的宏 typedef int BOOL define FALSE 0 define TRUE 1 其实是个int类型 占四个字
  • 学习笔记1.STM32HAL库之点灯

    学习笔记1 STM32HAL库之点灯 前段时间学习了51单片机的相关知识 接下来进行32的学习 这里我使用的是野火的stm32f103v6核心板 进入正题 1 首先打开cubemx 进行相关配置 选择SYS 在debug中选择烧录方式 Se
  • codeforces 950 #469 div2 D A Leapfrog in the Array

    Problem codeforces com contest 950 problem D Reference Codeforces Round 469 Div 2 D A Leapfrog in the Array 思维 Meaning 开
  • 单链表的插入和删除

    前言 在上一篇文章 单链表的定义 中我们已经了解了单链表的含义和简单的实现 那么在这篇文章中 我们将要来讲解单链表的插入和删除操作 按位序插入 带头结点 我们在上篇文章中已经讲解过 如果想要在表L中的第i个位置上插入指定元素e 我们需要找到
  • 认识爬虫:提取网站 cookie 信息,并使用 cookie 信息实现登录

    为什么要使用 cookie 信息来进行爬虫呢 做后端的朋友们都知道 一般情况下 在服务器上发布接口都是要设置身份信息验证 验证的方式就是通过 cookie 信息中包含的身份认证来进行验证 在身份验证通过之后 才能获取到响应接口的信息 所以
  • 实现锚点-scroll平滑滚动

    a链接锚点定位太生硬 试试自己让滚动条平滑滚动把 scroll2 target gt console log alb console log 滚动拉 target target target aaa className const scro
  • 使用动态规划解决分钱方案-2023年全国青少年信息素养大赛Python复赛真题精选

    导读 超平老师计划推出 全国青少年信息素养大赛Python编程真题解析 50讲 这是超平老师解读Python编程挑战赛真题系列的第14讲 全国青少年信息素养大赛 原全国青少年电子信息智能创新大赛 是 世界机器人大会青少年机器人设计与信息素养