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

文章目录

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

139.单词拆分

力扣题目链接

文章讲解:139.单词拆分

视频讲解:你的背包如何装满?| LeetCode:139.单词拆分

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

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

题目中要求我们用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。然后非零下标为了不影响赋值所以都初始化成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单类物品数量

背包问题总结篇

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

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

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

相关文章

70.网络游戏逆向分析与漏洞攻防-角色与怪物信息的更新-整理与角色数据更新有关的数据

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 如果看不懂、不知道现在做的什么&#xff0c;那就跟着做完看效果 现在的代码都是依据数据包来写的&#xff0c;如果看不懂代码&#xff0c;就说明没看懂数据包…

神经网络中常见的激活函数:理解与实践

神经网络中常见的激活函数&#xff1a;理解与实践 在神经网络中&#xff0c;激活函数是一个非常重要的组成部分&#xff0c;它为神经元引入了非线性特性&#xff0c;使得神经网络可以拟合各种复杂的函数关系。本文将介绍9种常见的激活函数&#xff0c;包括它们的概述、公式以及…

【开源设计】京东慢SQL组件:sql-analysis

京东慢SQL组件&#xff1a;sql-analysis 一、背景二、源码简析三、总结 地址&#xff1a;https://github.com/jd-opensource/sql-analysis 一、背景 开发中&#xff0c;无疑会遇到慢SQL问题&#xff0c;而常见的处理思路都是等上线&#xff0c;然后由监控报警之后再去定位对应…

unity入门——按钮点击了却无法调用函数

查阅了一番都没有解决问题&#xff0c;最后发现问题是由button的Onclick()事件绑定了代码脚本而不是游戏对象导致的。 如果Onclick()事件绑定的是代码脚本&#xff0c;则下拉框里没有函数&#xff0c;但是点击MonoScript后能手动填入函数名&#xff08;本以为这样就能实现调用…

JavaScript百炼成仙自学笔记——2

一、循环遍历&#xff1a; 方式一 for(var i0;i<10;i){console.log(i); }方式二 var i 0; while(i < 100){console.log(i);i; }细看代码就是 先定义变量i&#xff0c;再执行{}中的代码&#xff0c;最后改循环变量的值 二、遍历 什么事遍历&#xff1f; 什么时候会用…

SpringBoot中阿里OSS简单使用

官方文档:Java跨域设置实现跨域访问_对象存储(OSS)-阿里云帮助中心 1.pom中引入依赖 <dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.15.1</version> </dependency> 如…

图床搭建GitHub+PicGo+jsdelivr(CDN)+Typora(内附加速工具)

目录 安装PicGo GitHub配置与加速器 配置PicGo 使用typroa 安装PicGo PicGo是一个用于上传图片的客户端&#xff0c;支持拖拽上传、剪贴板上传&#xff0c;功能十分方便。 下载地址&#xff1a; https://github.com/Molunerfinn/PicGo/releases 个人网盘自取版本2.4.0…

高颜值管理系统界面,我敢保证你肯定看不够,看了又看。

有不少老铁&#xff0c;还坚持10年前的老思路&#xff0c;总觉得B端管理系统颜值不颜值不重要&#xff0c;关键是好用就行&#xff0c;这就犯了二元论的错误。 谁说高颜值的管理系统&#xff0c;就不好用了呢&#xff1f;高颜值和易用性冲突吗&#xff1f;我看未必吧。看看大厂…

SSL certificate problem: unable to get local issuer certificate【鸿蒙报错已解决】

文章目录 项目场景:问题描述原因分析:解决方案:此Bug解决方案总结Bug解决方案寄语项目场景: 最近也是遇到了这个问题,看到网上也有人在询问这个问题,本文总结了自己和其他人的解决经验,解决了【SSL certificate problem: unable to get local issuer certificate】的问…

制作一个 rpm 软件包

首发日期 2024-04-30, 以下为原文内容: 本文以 ibrus (艾刷, 胖喵拼音 ibus 接口模块) 为例, 介绍 rpm 软件包的制作过程. 相关文章: 《发布 AUR 软件包 (ArchLinux)》 https://blog.csdn.net/secext2022/article/details/136803790《多种双拼方案的实现》 https://blog.csdn.…

STM32(c语言基础)

1.硬件部分&#xff1a;按键&#xff0c;传感器 传感器模块&#xff1a;光敏电阻&#xff0c;热敏电阻&#xff0c;红外接收管 光敏电阻&#xff1a;光线越强&#xff0c;光敏电阻的阻值就越小&#xff1b; 热敏电阻&#xff1a;温度越高&#xff0c;热敏电阻的阻值越小&…

【全网首发】2024五一数学建模ABC题保奖思路(后续会更新)

一定要点击文末的卡片哦&#xff01; 1&#xff09;常见模型分类 机理分析类&#xff1a;来源于实际问题&#xff0c;需要了解一定的物理机理&#xff0c;转化为优化问题。 运筹优化类&#xff1a;旨在找到使某个目标函数取得最大或最小值的最优解,对于机理要求要求不高&…

Linux下安装snaphu

1、官网下载安装包 2、解压&#xff0c;移动文件夹到/usr/local/下 3、在/usr/local/下创建man&#xff0c;在man下创建man1文件夹 4、进入到snaphu的src文件夹里&#xff0c;执行sudo make&#xff0c;如果报错 在这个 Makefile 中&#xff0c;-arch x86_64 是 macOS 特定的…

三种滤波(EKF、UKF、CKF)的对比,含MATLAB源代码

使用MATLAB模拟三维的滤波,包含扩展卡尔曼滤波EKF、无迹卡尔曼滤波UKF、容积卡尔曼滤波CKF。 状态更新和观测更新均为非线性的,模拟一定强度的机动性,可用于卡尔曼滤波方法的对比学习,自己修改成需要的运动模型后,可以用于组合导航(GPS+DVL形式)。 运行结果 真值的三轴…

Docker容器---Harbor私有仓库部署与管理

一、搭建本地私有仓库 1、下载registry镜像 [rootlocalhost ~]#docker pull registry Using default tag: latest latest: Pulling from library/registry 79e9f2f55bf5: Pull complete 0d96da54f60b: Pull complete 5b27040df4a2: Pull complete e2ead8259a04: Pull comp…

移植 SquareLine 导出的 UI 源码到 HMI-Board

目录 准备工具创建 HMI 工程设计 UIUI 移植板级验证更多内容 HMI-Board 为 RT-Thread 联合瑞萨推出的高性价比图形评估套件&#xff0c;取代传统的 HMI 主控板 硬件&#xff0c;一套硬件即可实现 HMI IoT 控制 的全套能力。依托于瑞萨高性能芯片 RA6M3 及 RT-Thread 软件生态…

mysql数据库navicat数据同步时误删除部分数据

背景介绍 听说过删库跑路被抓的&#xff0c;今天就碰到升级服务器&#xff08;Alibaba Cloud Linux ----> Ubuntu&#xff09;原因是taos3.2不支持Alibaba Cloud Linux系统&#xff01; 为了保险起见把现在这个数据库里的数据都备份一份&#xff0c;为了不耽误同事们继续开…

渐悟之程序员

目录 感谢互联网为什么选择这行&#xff1f;现在的现状未来的展望多说几句好好学习&#xff0c;好好工作&#xff0c;好好生活&#xff0c;好好活着&#xff0c;共勉&#xff01; 就是一篇流水文&#xff0c;没什么质量&#xff0c;权当给各位看客打发时间 行路难&#xff0c;行…

Jenkins构建触发器-触发远程构建-构建后触发-定时构建-轮询SCM

系列文章目录 文章目录 系列文章目录前言前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。 Jenkins是一个开源的、提供友好操作界面的持续集成(CI)工具,起源于Hudso…

第12章 软件测试基础(第三部分)测试类型

七、测试类型&#xff08;按工程阶段划分&#xff09; 单集系确收 &#xff08;一&#xff09;单元测试 1、单元测试/模块测试 单元就是软件中最小单位&#xff08;或模块&#xff09;。可以是一个函数、一个过程、一个类。主要依据是模块的详细设计文档。价值在于尽早发现…