【每日一题】【动态规划(DP) 】【分治 迭代】“葡萄城杯”牛客周赛 Round 53 D题 小红组比赛 C++

news2024/11/23 19:14:57

“葡萄城杯”牛客周赛 Round 53 D题

小红组比赛

题目背景

“葡萄城杯”牛客周赛 Round 53

题目描述

小红希望出一场题目,但是他的实力又不够,所以他想到可以从以前的比赛中各抽一题,来组成一场比赛。不过一场比赛的难度应该是有限制的,所以所以这一场比赛会给一个目标难度分数 t a r g e t target target

小红选 n n n场比赛,每场 m m m个题,小红会从每一场选一道题,使其组成的题的难度分数尽量接近 t a r g e t target target。小红想知道挑选的题的难度分数与 t a r g e t target target相差的最小值是多少。

输入格式

第一行包含两个正整数 n , m ( 1 ≤ n ≤ 100 , 1 ≤ m ≤ 20 ) n, m(1\le n \le 100 ,1 \le m \le 20) n,m(1n100,1m20)代表小红选了 n n n场比赛,每场比赛有 m m m道题。

此后 n n n 行,第 i i i行输入 m m m个整数 a i , j ( 1 ≤ a i , j ≤ 50 ) a_{i,j}(1\le a_{i,j} \le 50) ai,j(1ai,j50) 代表第 i i i场比赛的第 j j j道题的难度分数。

最后一行输入一个整数 t a r g e t ( 1 ≤ t a r g e t ≤ 5000 ) target (1 \le target \le 5000) target(1target5000)代表小红希望这一场比赛的难度分数。

输出格式

在一行上输出一个整数,表示挑选的题的难度分数与 t a r g e t target target相差的最小值。

样例 #1

样例输入 #1

3 3
1 4 7
2 5 8
3 6 9
10

样例输出 #1

1
说明

小红可以选第一场比赛的第一道题,第二场比赛的第一道题,第三场比赛的第二道题,这样挑选的题的难度分数为 1 + 2 + 6 = 9 1+2+6=9 1+2+6=9,与 t a r g e t target target相差的最小值为 1 1 1

做题要点

  1. 小红会从每一场选一道题
  2. 组成的题的难度分数尽量接近 t a r g e t target target
  3. 1 ≤ n ≤ 100 , 1 ≤ m ≤ 20 1\le n \le 100 ,1 \le m \le 20 1n100,1m20

做题思路

因为 1 ≤ n ≤ 100 , 1 ≤ m ≤ 20 1\le n \le 100 ,1 \le m \le 20 1n100,1m20,如果用普通的dfs去遍历枚举每一种情况的话,时间复杂度将会来到 O ( m n ) O(m^n) O(mn),必定是不可以的,而且数据严苛的话,很难通过剪枝优化去大幅度削减时间复杂度。

第一个思考起点基于分治法
分治策略为递归地求解一个问题,每层递归中有三个步骤:

  1. 分解步骤将问题分为一些子问题,子问题的形式和原问题一样,只是规模更小
  2. 解决步骤递归地求解出子问题,如果子问题的规模足够小,则停止递归,直接求解。
  3. 合并步骤将子问题组合成原问题的解。

那么应用在这一题原问题选择 n n n个题目,分为子问题的话就是选择 n − 1 n-1 n1个题目。因为目标不好分为子问题,但看到 m m m的规模小和 t a r g e t < = 5000 target<=5000 target<=5000,如果能列出子问题的所有情况,就可以得出答案。

根据输入样例

1 4 7
2 5 8
3 6 9

子问题的规模足够小也就意味着选择一个题目。

选择一个题目有 1 , 4 , 7 1,4,7 1,4,7三种

那么选择两个题目实际上就在这三种情况上分别加上 2 , 5 , 8 2,5,8 2,5,8
也就变为 1 + 2 , 4 + 2 , 7 + 2 , 1 + 5 , 4 + 5 , 7 + 5 , 1 + 8 , 4 + 8 , 7 + 8 1+2,4+2,7+2,1+5,4+5,7+5,1+8,4+8,7+8 1+2,4+2,7+2,1+5,4+5,7+5,1+8,4+8,7+8这九种情况(考虑重复)

那么选择三个题目实际上在这九种情况上再分别加上 3 , 6 , 9 3,6,9 3,6,9

以上是步骤可以称为分治策略里的合并步骤。

第二个思考起点基于迭代法
上述的分治有分有合,但实际情况来说思路可以分解,实际操作不用分解。

选择一个题目所有的情况得出后,就可以直接基于选择一个题目的情况得到选择两个题目的所有情况。

以此类推 n ≤ 100 n\le 100 n100,也就是说最多迭代100次就可以出结果。

其中每次只需要在前面的情况加上最多 m ≤ 20 m \le 20 m20个数字。

有一个问题就在于如果不知道 t a r g e t < = 5000 target<=5000 target<=5000且$a_{i,j}\le 50 $那么就无法限制住情况的个数。

在上面的例子可以得到 m = 3 , n = 2 m=3,n=2 m=3,n=2的时候就可能有九种不重复情况,如果不限制进行迭代,第 k k k次迭代(选择 k k k个题目)的时候就可能出现 m k m^k mk个不重复的情况。在时间复杂度的考虑上和普通的dfs一样糟糕。

而题目说了 t a r g e t < = 5000 target<=5000 target<=5000 a i , j ≤ 50 a_{i,j}\le 50 ai,j50,意味着如果超过 5000 5000 5000的情况就可以舍去了。原因:
a i , j ≤ 50 a_{i,j}\le 50 ai,j50 n ≤ 100 n\le 100 n100 , 那么 ∑ i = 1 n max ⁡ j = 1 m a i , j ≤ 50 × 100 \displaystyle\sum_{i=1}^{n}\displaystyle\max_{j=1}^{m}a_{i,j} \le 50\times 100 i=1nj=1maxmai,j50×100

所以每次迭代的范围就定在了 0 到 5000 0到5000 05000

第三思考起点基于动态规划(dp)

范围定了,思路也有了,那么如何去编程是重点。

因为每次迭代都基于上一个“子问题”的情况。

所以要一个记录情况的数组。因为范围已经确定了,所以开个定长的数组即可。

这里给出的方案为开足够长( > 5000 \gt 5000 >5000)的二维布尔数组。

第一个纬度表示迭代次数/选择题目的个数,第二个纬度表示难度和。

b i , j = t r u e b_{i,j} = true bi,j=true表示选择了 i i i个题目使得难度和 j j j的情况存在。

每次每次迭代都基于上一个“子问题”的情况并且已知选择第 i i i次的题目难度
那么如果 b i − 1 , k − a i , j = t r u e b_{i-1,k-a_{i,j}} = true bi1,kai,j=true,那么 b i , k = t r u e b_{i,k} = true bi,k=true
其含义为,如果选择 i − 1 i-1 i1个题目使得难度和 k − a i , j k-a_{i,j} kai,j的情况存在,那么在第 i i i次选择中选择难度为 a i , j a_{i,j} ai,j难度的题目,就可以使得选择 i i i个题目难度和 a i , j a_{i,j} ai,j的情况存在

在动态规划中 b i , j b_{i,j} bi,j称为状态,而 b i , k ∣ = b i − 1 , k − a i , j b_{i,k} |= b_{i-1,k-a_{i,j}} bi,k=bi1,kai,j称为状态转移方程(符号 ∣ | 表示按位或)。

一道题没选的时候难度和只能是0,所以 b 0 , 0 = t r u e b_{0,0} = true b0,0=true初始状态

基于滚动数组的二次优化(空间复杂度上的)
因为状态转移方程只涉及到两组状态,分别是上一次迭代和本次迭代,所以可以只开两个足够长一维布尔数组。然后轮流迭代记录即可实现本题。

总思路

  1. 初次迭代为什么都不选,即 b 0 , 0 = t r u e b_{0,0} = true b0,0=true
  2. 每次迭代, b i , k ∣ = b i − 1 , k − a i , j b_{i,k} |= b_{i-1,k-a_{i,j}} bi,k=bi1,kai,j
  3. 最后得出选完 n n n个题目所有难度情况,并选出与 t a r g e t target target差值最小的

核心代码对应思路

memset(b,false,sizeof(b));
b[0][0] = true;
for(int i=1;i<=n;i++){
    for(int j=1;j<=m;j++){
        for(int k=a[i][j];k<=5050;k++){
            b[i][k] |= b[i-1][k-a[i][j]];
        }
    }
}
  1. 初次迭代为什么都不选,即 b 0 , 0 = t r u e b_{0,0} = true b0,0=true
  2. 每次迭代, b i , k ∣ = b i − 1 , k − a i , j b_{i,k} |= b_{i-1,k-a_{i,j}} bi,k=bi1,kai,j
  3. 最后得出选完 n n n个题目所有难度情况,并选出与 t a r g e t target target差值最小的

迭代 n n n次,每次有 m m m个选择
其中迭代范围为 0 到 5000 0到5000 05000。(这里做题的时候没有细细验证所以定到了5050)
注意:
k k k的起点为 a i , j a_{i,j} ai,j是因为状态转移方程含有 k − a [ i ] [ j ] k-a[i][j] ka[i][j],只有 k − a [ i ] [ j ] ≥ 0 k-a[i][j] \ge 0 ka[i][j]0才有意义,所以当 k = a [ i ] [ j ] k = a[i][j] k=a[i][j]时候符合范围条件。

时间复杂度分析

读入时间复杂度为 O ( n × m ) O(n\times m) O(n×m)
迭代过程时间复杂度为 O ( 5000 n × m ) O(5000n\times m) O(5000n×m)
总时间复杂度约为 1 0 7 10^7 107

伪代码

在这里插入图片描述

代码

#include <iostream>
#include <vector>
#include <queue>
#include <tuple>
#include <map>
#include <cstring>
#include <algorithm>

using namespace std;
const int N = 1e3+10;
const int INF = 0x3f3f3f3f;
int n,m,target;
int a[N][N];
bool b[110][(int)5e3+50];
int ans = INF,now=0;
void init(){

}
int main(){
    init();
    cin >> n >> m;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            cin >> a[i][j];
    cin >> target;
    memset(b,false,sizeof(b));
    b[0][0] = true;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            for(int k=a[i][j];k<=5050;k++){
                b[i][k] |= b[i-1][k-a[i][j]];
            }
        }
    }
    for(int k=0;k<=5050;k++){
        if(b[n][k])
            ans = min(ans,abs(k-target));
    }
    cout << ans;
    return 0;
}

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

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

相关文章

【nginx】nginx日志出现on文件

问题描述 生产发现容器里多出了一个on文件&#xff0c;非常大。 去看nginx配置已经这样保持16个月了&#xff08;已经去掉其他无关内容&#xff09; 原因解释 这个问题是因为nginx配置了access_log on; 有两个知识点&#xff1a; 1.access_log只有off的特殊值&#xff0c…

三菱电火花设备采集

三菱电火花机器一般情况下应该很少能见到,但在模具行业应该说是一种常见的加工设备。 一、通过官方手册采集数据 1.资料使用 连接方式: 这里重点关注下端口是1112 这里主要讲NC的状态转换 我们重点关注的是状态相关命令,手册中还支持NC程序上传和下载,感兴趣的话可以研究…

排序算法:堆排序,golang实现

目录 前言 堆排序 代码示例 1. 算法包 2. 堆排序代码 3. 模拟程序 4. 运行程序 5. 从大到小排序 堆排序的思想 堆排序的实现逻辑 1. 构建最大堆 2. 排序 循环次数测试 假如 10 条数据进行排序 假如 20 条数据进行排序 假如 30 条数据进行排序 假设 5000 条数据…

数据库——战德臣

1. 数据存储体系 1.1 计算机系统的存储体系 1.将不同性价比的存储组织在一起&#xff0c;满足高速的、大容量、低价格需求 2.CPU与内存直接交换信息&#xff0c;按存储单元&#xff08;存储字&#xff09;进行访问 3.外存按存储块进行访问&#xff0c;其信息先装入内存&…

NSSCTF-GDOUCTF 2023新生赛

[GDOUCTF 2023]hate eat snake 考察&#xff1a;js代码审计 打开题目&#xff0c;发现需要坚持60秒&#xff0c;那么简单的一个思路就是修改得分的变量>60即可 办法1&#xff1a;修改变量 右键查看源代码&#xff0c;之后发现有一个snake.js的文件&#xff0c;ctrlf搜索i…

健康小贴士丨中考考生怎么吃得好?

文章目录 引言三餐最佳的进食时间引言 中考正值初夏,气温急剧升高,食物易滋生细菌,发生食物中毒的风险也随之增加,医生建议 选择新鲜的食材,煮熟煮透,现吃现做,尽量不食用剩饭剩菜;不在路边露天摊点、不到无证和食品安全状况差的餐馆用餐;尽量减少在外就餐和点外卖的…

客服中心:高效知识库管理,6步提高70%用户体验

在当今快节奏的商业环境中&#xff0c;客服中心作为企业与客户沟通的重要桥梁&#xff0c;其运作的顺畅与否直接影响着客户的满意度和忠诚度。而知识库作为客服中心的核心资源之一&#xff0c;其管理水平的高低更是直接影响着客服的工作效率和问题解决能力。本文将深入探讨一系…

Django之JsonResponse对象

【图书介绍】《Django 5企业级Web应用开发实战&#xff08;视频教学版&#xff09;》_django 5企业级web应用开发实战(视频教学版)-CSDN博客 《Django 5企业级Web应用开发实战&#xff08;视频教学版&#xff09;》(王金柱)【摘要 书评 试读】- 京东图书 (jd.com) 在Django框…

“LangChain实战:探索回调函数的应用

前言 毫无疑问&#xff0c;2024将是人工智能丰收年&#xff0c;开始寒假的我&#xff0c;准备先把LangChain捋一遍。 这篇文章来学习下callback机制&#xff0c; 之前聊过AutoGen的callback机制&#xff0c;我们来对比下。 回调和异步 作为js开发者&#xff0c;对于回调函数…

springboot智能健康管理平台-计算机毕业设计源码57256

摘要 在当今社会&#xff0c;人们越来越重视健康饮食和健康管理。借助SpringBoot框架和MySQL数据库的支持&#xff0c;开发智能健康管理平台成为可能。该平台结合了小程序技术的便利性和SpringBoot框架的快速开发能力&#xff0c;为用户提供了便捷的健康管理解决方案。 通过智能…

无线磁吸充电宝哪个牌子值得入手?什么牌子磁吸充电宝性价比高?

在当下科技日新月异的时期&#xff0c;无线磁吸充电宝成为了众多电子设备用户的得力助手。然而&#xff0c;面对市场上众多品牌和型号的无线磁吸充电宝&#xff0c;消费者常常陷入选择的困境&#xff1a;到底哪个牌子值得入手&#xff1f;什么牌子的磁吸充电宝性价比高&#xf…

【JavaScript】详解默认导出和命名导出的区别

文章目录 一、默认导出二、命名导出三、默认导出和命名导出的区别四、实际应用案例五、总结 在JavaScript模块化开发中&#xff0c;导入和导出模块是核心操作。ES6引入的模块化语法提供了两种主要的导出方式&#xff1a;默认导出&#xff08;default export&#xff09;和命名导…

【2024蓝桥杯/C++/B组/宝石组合】

代码来源2024第十五届蓝桥杯 C/CB组真题题解_蓝桥杯2024b组c语言答案-CSDN博客 证明s的简化式子

【Linux】命令行通配符

Linux在文件管理方面提供了丰富的功能&#xff0c;例如通配符&#xff0c;它是一种用于匹配文件名的特殊字符。通配符在Linux中可以帮助我们更加方便和快捷地查找和操作文件。 1.命令行通配符 通配符是一种特殊语句&#xff0c;主要有星号(*)、问号(?)等表示&#xff0c;用来…

记一个搞笑的自写类加载TemplatesImpl

今天没事想自己写个CC3类加载 结果为了顺利触发到TemplatesImpl#getTransletInstance的newInstance给我整急眼了&#xff0c;使劲改字段强行通过循环 结果搞了个下面的代码出来 import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; import com.sun.org.apa…

手机买对不买贵!性价比之王再升级,致敬奋斗者

众所周知&#xff0c;比起旗舰机&#xff0c;中端机一年要发几次新款机型&#xff0c;因此&#xff0c;一两千元的价位段就尤其的卷。那此时作为消费者的我们就是赚了&#xff0c;花更少的钱就能买到更好的产品。华为畅享70S这款手机是今年最新的一款针对性价比用户推出的千元机…

大厂面试必备的软件测试八股文【附答案】

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 前言 最近有很多粉丝问我&#xff0c;有什么方法能够快速提升自己&#xff0c;通过阿里、腾讯、字节跳动、京东等互联网大厂的面试&#xff0c;我觉得短时间提升…

7ECloud云服务器在视频流服务器中的应用

视频现在已然是人们之间互相传递的一种信息形式&#xff0c;而视频内容也是娱乐消费的主要形式之一&#xff0c;媒体平台想要提供高效&#xff0c;稳定的视频流服务也成为了行业关注的焦点之一。7ECloud云服务器展现出的计算能力&#xff0c;灵活的资源调度能力以及高度扩展性等…

【中项】系统集成项目管理工程师-第9章 项目管理概论-9.3项目经理的角色与9.4项目生命周期和项目阶段

前言&#xff1a;系统集成项目管理工程师专业&#xff0c;现分享一些教材知识点。觉得文章还不错的喜欢点赞收藏的同时帮忙点点关注。 软考同样是国家人社部和工信部组织的国家级考试&#xff0c;全称为“全国计算机与软件专业技术资格&#xff08;水平&#xff09;考试”&…