代码随想录算法训练营DAY46|C++动态规划Part8|139.单词拆分、多重背包理论基础、背包问题总结篇

文章目录

  • 139.单词拆分
    • 思路
    • CPP代码
  • 多重背包理论基础
    • 处理输入
    • 把所有个数大于1的物品展开成1个
    • 开始迭代,计算dp数组
    • 代码优化
  • 背包问题总结篇

139.单词拆分

力扣题目链接

文章讲解:139.单词拆分

视频讲解:你的背包如何装满?| LeetCode:139.单词拆分
状态:本题主要还是两个地方要注意:一个是s.substr的使用,另外一个就是遍历顺序,最后是对内循环循环终止条件的考量.

本题其实是可以使用回溯算法来写的,具体可以直接去看卡哥的文章:回溯算法和优化思路

如果使用动态规划应该怎么写呢?

题目中要求我们用wordDict中的元素,看能不能组合成字符串s,其实已经很直观了!

也就是说我们的物品是wordDict,背包容量是s,看这些物品能不能正好装满这个背包。同时,题目中说了我们的物品元素是能够使用多次的,所以本题是一道很奈斯的完全背包问题!

思路

  • dp数组含义

如果这个字符串长度为i,如果能被wordDict的单词组成的话,那么dp[i]=true,最终的结果其实就是dp[s.size]到底是true还是false(我们用dp[0]来表示空字符串的状态)

  • 递推公式

这个递推公式其实蛮复杂的该说不说。这里数形结合进行表示

如果 我们的dp[j]为true,并且我们的N子段为wordDict中的元素,那就可以完美推导出dp[i]也为true

if (wordSet.find(N) != wordSet.end() && dp[j]==true)dp[i]=true 
  • 初始化
    这里的初始化很重要,dp[0]必须初始化成true,如果dp[0]初始化成false的话对导致后面的推导全部是false(因为我们仍然要借助前面的dp[j]来判断后面的dp[i])。然后非零下标为了不影响赋值所以都初始化成false

  • 遍历顺序

对于完全背包问题,两层for循环的讨论非常有必要,这里再次做总结

如果求组合数就是外层for循环遍历物品,内层for遍历背包

如果求排列数就是外层for遍历背包,内层for循环遍历物品

求组合数的题有:518.零钱兑换II

求排列数的题有:377. 组合总和 Ⅳ 、70. 爬楼梯进阶版(完全背包)

求最小数的题有:322. 零钱兑换 、279.完全平方数


在本题中,我们求的很明显是排列数,也就是说关注顺序,比如说s = “applepenapple”, wordDict = [“apple”, “pen”]

“apple”, “pen” 是物品,那么我们要求 物品的组合一定是 “apple” + “pen” + “apple” 才能组成 “applepenapple”。

“apple” + “apple” + “pen” 或者 “pen” + “apple” + “apple” 是不可以的,那么我们就是强调物品之间顺序。

所以本题一定是先遍历背包,再遍历物品。

  • 打印

以输入: s = “leetcode”, wordDict = [“leet”, “code”]为例,dp状态如图:

CPP代码

class Solution {
public:bool wordBreak(string s, vector<string>& wordDict) {unordered_set<string> wordSet(wordDict.begin(), wordDict.end());vector<bool> dp(s.size() + 1, false);dp[0] = true;for (int i = 1; i <= s.size(); i++) {   // 遍历背包for (int j = 0; j < i; j++) {       // 遍历物品string word = s.substr(j, i - j); //substr(起始位置,截取的个数)if (wordSet.find(word) != wordSet.end() && dp[j]) {dp[i] = true;}}}return dp[s.size()];}
};
  • 时间复杂度:O(n^3),因为substr返回子串的副本是O(n)的复杂度(这里的n是substring的长度)
  • 空间复杂度:O(n)

多重背包理论基础

卡码网第56题

文章讲解:多重背包理论基础

什么叫多重背包问题呢?其实就是在01背包的基础上多了一个物品数量的维度。

重量价值数量
物品01152
物品13203
物品24302

可以转换成01背包问题吗?必须的

重量价值数量
物品01151
物品01151
物品13201
物品13201
物品13201
物品24301
物品24301

处理输入

题目中谈到,“宇航舱最大容量为C”,即背包的最大容量为C;
“有N种不同的矿石”,表示物品的种类有N个;
每种矿石有一个重量w[i],一个价值v[i],以及最多k[i]个可用,这段描述可以确定是典型的多重背包问题。输入形式如下:

输入共包括四行,第一行包含两个整数 C 和 N,分别表示宇航舱的容量和矿石的种类数量。
接下来的三行,每行包含 N 个正整数。具体如下:
第二行包含 N 个整数,表示 N 种矿石的重量。
第三行包含 N 个整数,表示 N 种矿石的价格。
第四行包含 N 个整数,表示 N 种矿石的可用数量上限。

int bagWeight, n;
cin >> bagWeight >> n;
vector<int> weight(n, 0);
vector<int> value(n, 0);
vector<int> nums(n, 0);
for (int i = 0; i < n; i++) cin >> weight[i];
for (int i = 0; i < n; i++) cin >> weight[i];
for (int i = 0; i < n; i++) cin >> weight[i];

把所有个数大于1的物品展开成1个

展开的过程不在乎顺序,直接往对应数组后面插即可

for (int i = 0; i < n; i++) {while (nums[i] > 1) { //物品数量不是一的,都展开weight.push_back(weight[i]);value.push_back(value[i]);nums[i]--}
}

开始迭代,计算dp数组

完全按照01背包的搞法来整

vector<int> dp(bagWeight + 1, 0);
for (int i = 0; i < weight.size(); i++) {for (int j = bagWeight; j >= weight[i]; j--) {dp[j] = max(dp[j], dp[j - weight[i]] + value[i];}cout << dp[bagWeight] << endl;
}

代码优化

如果提交刚刚那段代码,我们会发现代码超时了
我们再来审视一下之前的代码,其实出问题的就在于vector底层的动态扩容,虽然根据扩容操作的平摊事件时间复杂度,vector底层的动态扩容应该是O(1),但是数据量较大的时候还是会遇到插入延迟,所以我们应该对其进行优化。

for (int i = 0; i < n; i++) {while (nums[i] > 1) { // 物品数量不是一的,都展开weight.push_back(weight[i]);value.push_back(value[i]);nums[i]--;}
}
  • 我们可以先把所有物品数量都计算好,然后一起申请vector的空间。
    //方法:reserve// 计算总共需要的空间int totalItems = 0;for (int i = 0; i < n; i++) {totalItems += nums[i];}vector<int> expandedWeight;vector<int> expandedValue;expandedWeight.reserve(totalItems); // 预分配足够的空间expandedValue.reserve(totalItems);// 填充物品for (int i = 0; i < n; i++) {for (int count = 0; count < nums[i]; count++) {expandedWeight.push_back(weight[i]);expandedValue.push_back(value[i]);}}//方法二:resize// 计算总共需要的空间int totalItems = 0;for (int i = 0; i < n; i++) {totalItems += nums[i];}// 使用 resize 预设大小,并在原数组上操作weight.resize(totalItems);value.resize(totalItems);int index = n; // 从原始数组大小开始填充新元素for (int i = 0; i < n; i++) {for (int count = 1; count < nums[i]; count++) { // 已有一个初始元素,所以从1开始weight[index] = weight[i];value[index] = value[i];index++;}}
  • 再就是把每种商品遍历的个数放在01背包里面一起遍历
//最终代码
#include<iostream>
#include<vector>
using namespace std;
int main() {int bagWeight,n;cin >> bagWeight >> n;vector<int> weight(n, 0);vector<int> value(n, 0);vector<int> nums(n, 0);for (int i = 0; i < n; i++) cin >> weight[i];for (int i = 0; i < n; i++) cin >> value[i];for (int i = 0; i < n; i++) cin >> nums[i];vector<int> dp(bagWeight + 1, 0);for(int i = 0; i < n; i++) { // 遍历物品for(int j = bagWeight; j >= weight[i]; j--) { // 遍历背包容量// 以上为01背包,然后加一个遍历个数for (int k = 1; k <= nums[i] && (j - k * weight[i]) >= 0; k++) { // 遍历个数dp[j] = max(dp[j], dp[j - k * weight[i]] + k * value[i]);}}}cout << dp[bagWeight] << endl;
}

时间复杂度:O(m × n × k),m:物品种类个数,n背包容量,k单类物品数量

背包问题总结篇

背包问题中关于初始值的设定只有两种情况:

  1. 关于下标0的设定紧贴dp数组的含义
  2. 关于非零下标的设置要防止后续推导的值被覆盖

二刷后完成总结,这里先贴上卡哥的文章背包问题总结篇

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

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

相关文章

计算方法实验9:Romberg积分求解速度、位移

任务 输出质点的轨迹 ( x ( t ) , y ( t ) ) , t ∈ { 0.1 , 0.2 , 0.3 , . . . , 10 } (x(t), y(t)), t\in \{0.1, 0.2, 0.3, ..., 10\} (x(t),y(t)),t∈{0.1,0.2,0.3,...,10}&#xff0c;并在二维平面中画出该轨迹.请比较M分别取4, 8, 12, 16, 20 时&#xff0c;Romberg积分达…

蓝桥杯省三爆改省二,省一到底做错了什么?

到底怎么个事 这届蓝桥杯选的软件测试赛道&#xff0c;都说选择大于努力,软件测试一不卷二不难。省赛结束&#xff0c;自己就感觉稳啦&#xff0c;全部都稳啦。没想到一出结果&#xff0c;省三&#xff0c;g了。说落差&#xff0c;是真的有一点&#xff0c;就感觉和自己预期的…

汽车软件研发工具链丨怿星科技新产品重磅发布

“创新引领未来”聚焦汽车软件新基建&#xff0c;4月27日下午&#xff0c;怿星科技2024新产品发布会在北京圆满举行&#xff01;智能汽车领域的企业代表、知名大企业负责人、投资机构代表、研究机构代表齐聚现场&#xff0c;线上直播同步开启&#xff0c;共同见证怿星科技从单点…

经典回溯算法之N皇后问题

问题描述&#xff1a; 有一个N*N的棋盘&#xff0c;需要将N个皇后放在棋盘上&#xff0c;保证棋盘的每一行每一列每一左斜列每一右斜列都最多只能有一个皇后。 按照国际象棋的规则&#xff0c;皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如…

Java | Leetcode Java题解之第71题简化路径

题目&#xff1a; 题解&#xff1a; class Solution {public String simplifyPath(String path) {String[] names path.split("/");Deque<String> stack new ArrayDeque<String>();for (String name : names) {if ("..".equals(name)) {if …

【基于 PyTorch 的 Python 深度学习】5 机器学习基础(3)

前言 文章性质&#xff1a;学习笔记 &#x1f4d6; 学习资料&#xff1a;吴茂贵《 Python 深度学习基于 PyTorch ( 第 2 版 ) 》【ISBN】978-7-111-71880-2 主要内容&#xff1a;根据学习资料撰写的学习笔记&#xff0c;该篇主要介绍了单 GPU 加速和多 GPU 加速&#xff0c;以及…

英语口语情景对话视频软件分享!

在当今全球化的时代&#xff0c;英语已成为一种通用的国际语言。为了提高英语口语能力&#xff0c;越来越多的人选择使用英语口语情景对话视频软件。本文将为您推荐几款备受欢迎的英语口语情景对话视频软件&#xff0c;帮助您轻松提高英语口语水平。 AI外语陪练 AI外语陪练软件…

已经有 Prometheus 了,还需要夜莺?

谈起当下监控&#xff0c;Prometheus 无疑是最火的项目&#xff0c;如果只是监控机器、网络设备&#xff0c;Zabbix 尚可一战&#xff0c;如果既要监控设备又要监控应用程序、Kubernetes 等基础设施&#xff0c;Prometheus 就是最佳选择。甚至有些开源项目&#xff0c;已经内置…

LoRA的原理简介

在文章开始前先澄清一个概念&#xff0c;需要区分形近的单词"LoRa"&#xff08;long range&#xff09;&#xff0c;这是一项通信技术。熟悉物联网行业的朋友相对会比较熟悉LoRa这项技术&#xff0c;因为有些设备比如电梯的控制就使用了这个技术进行本地数据和命令的…

小红书释放被封手机号 无限注册

前几年抖音也可以释放被封手机号 那时候都不重视 导致现在被封手机号想释放 基本不可能的 或者就是最少几百块 有专业的人帮你通过某些信息差释放 本教程是拆解 小红书被封手机号怎么释放&#xff0c;从今年开始&#xff0c;被封的手机号无法注销了 所以很困扰 那么本教程来…

基于一种改进小波阈值的微震信号降噪方法(MATLAB)

微震是指岩体由于在人为扰动或自然原因下受力变形&#xff0c;发生破裂过程中能量积聚而释放的弹性波或应力波。微震信号具有信噪比低、不稳定性、瞬时性和多样性等特点。因此&#xff0c;在任何损坏之前都会出现微小的裂缝&#xff0c;这种微小的裂缝是由岩层中应力和应变的变…

PPT职场课:话术+技巧+框架+案例,告别只会念PPT不会讲(8节课)

课程目录 001-讲PPT如何开场及导入?5个简单实用的方法.mp4 002-讲PPT如何过渡衔接结尾?6类话术争来就用.mp4 003-掌握这3个逻辑表达万能框架&#xff0c;搞定98的PPT.mp4 004-学会这3种PPT结构讲解技巧告别只会念不会讲(上).mp4 005-学会这3种PPT结构讲解技巧告别只会念…

Logstash分析MySQL慢查询日志实践

删除匹配到的行&#xff0c;当前行信息不记录到message中

106网页短信群发平台

什么是106网页短信群发平台&#xff1f; 106网页短信群发平台是一种便捷的在线群发工具&#xff0c;通过该平台用户可以方便地向大量的手机号码*。相比传统的群发方式&#xff0c;106网页群发平台具有更高效、更便捷的特点。 为什么选择106网页短信群发平台&#xff1f; 高效快…

浙大×移动云,携手点亮AI新时代

近年来&#xff0c;中国移动依托强大的算网资源优势&#xff0c;围绕大模型训练、推理和应用三大场景&#xff0c;打造了一站式智算产品体系。该体系旨在为客户提供覆盖资源、平台、应用的AI全链路服务。目前&#xff0c;一站式智算产品体系已在浙江大学智算中心和许昌中原智算…

C++:编程界的王者,引领未来的创新之路

在编程语言的浩瀚星空中&#xff0c;C犹如一颗耀眼的恒星&#xff0c;以其卓越的性能、深厚的底蕴和广泛的应用领域&#xff0c;持续引领着编程界的发展。它不仅在当下拥有无可替代的地位&#xff0c;更在未来展现出无限的潜力和可能性。 一、C&#xff1a;编程界的王者风范 …

若依框架dialog弹窗取消点击空白出关闭

如果想全局取消的话就找到main.js在里面加上下面的一行代码&#xff0c;添加完成之后记得清楚浏览器缓存重新加载js文件。 Element.Dialog.props.closeOnClickModal.default false;如果想指定某个弹窗取消点击空白处关闭&#xff0c;那么就找到那个弹窗加上。添加完毕之后刷新…

【python】基于岭回归算法对学生成绩进行预测

前言 在数据分析和机器学习领域&#xff0c;回归分析是一种预测连续数值的监督学习技术。当数据特征与目标变量之间存在线性关系时&#xff0c;线性回归模型尤其有用。然而&#xff0c;当特征数量多于样本数量&#xff0c;或者特征之间存在多重共线性时&#xff0c;普通最小二…

unaipp推荐算法的汽车租赁系统zaxzu 微信小程序hbuiderx

随着现代汽车租赁管理的快速发展&#xff0c;可以说汽车租赁管理已经逐渐成为现代汽车租赁管理过程中最为重要的部分之一。但是一直以来我国传统的汽车租赁管理并没有建立一套完善的行之有效的汽车租赁管理系统&#xff0c;传统的汽车租赁管理已经无法适应高速发展&#xff0c;…

基于SpringBoot+Vue点餐系统设计和实现(源码+LW+部署讲解)

&#x1f339;作者简介&#xff1a;✌全网粉丝10W&#xff0c;前大厂员工&#xff0c;多篇互联网电商推荐系统专利&#xff0c;现有多家创业公司&#xff0c;致力于建站、运营、SEO、网赚等赛道。也是csdn特邀作者、博客专家、Java领域优质创作者&#xff0c;博客之星、掘金/华…