C++ day42背包理论基础01 + 滚动数组
背包问题的重中之重是01背包
01背包
有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。
每一件物品其实只有两个状态,取或者不取,所以可以使用回溯法搜索出所有的情况,那么时间复杂度就是o(2^n),这里的n表示物品数量。
所以暴力的解法是指数级别的时间复杂度。进而才需要动态规划的解法来进行优化!
举一个例子:背包最大重量为4,有3个物品,其重量和价值如下表
物品为:
| 重量 | 价值 | |
|---|---|---|
| 物品0 | 1 | 15 |
| 物品1 | 3 | 20 |
| 物品2 | 4 | 30 |
问背包能背的物品最大价值是多少?
动规五部曲
1)确定dp数组以及下标的含义
对于背包问题,有一种写法, 是使用二维数组,即dp[i][j] 表示从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少,i代表第几个物品,j代表背包的容量,dp[i][j]代表价值
2)递推公式
对于每一个物品都有放与不放两种状态,所以又有两种情况,取这两种情况的最大值

3)dp数组初始化
根据递推公式,可知dp数组是由其左上角和正上方推导而来,所以要对其第一行和第一列进行初始化

其他下标的价值由递推公式更新推导,所以其它地方初始化为任意值均可
4)遍历顺序
因为本题有两个维度,分别为物品维度和背包容量维度,所以到底是先遍历物品呢?还是先遍历背包呢?
可以分类讨论一下
先遍历物品

先遍历背包

5)打印dp数组
代码
int weight_bag(vector<int> weight,vector<int> value,int bagweight){vector<vector<int>> dp(weight.size(),vector<int>(bagweight+1,0));//初始化.对于物品0for(int j=weight[0];j<=bagweight;j++){dp[0][j]=value[0];}//递推(先遍历物品,再遍历背包)for(int i=1;i<weight.size();i++){for(int j=0;j<=bagweight;j++){if(j<weight[i]) dp[i][j]=dp[i-1][j];//如果当前物品重量比背包容量大,则装不下该物品//如果当前物品重量比背包容量小,那么可以有两种选择,装下该物品,或是不装该物品else dp[i][j]=max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i]);}}return dp[weight.size()-1][bagweight];
}
01背包(滚动数组)
把dp[i - 1]这一层拷贝到dp[i]上,只用一个一维数组dp[j],可以理解是一个滚动数组。
滚动数组需要满足的条件是上一层可以重复利用,直接拷贝到当前层,一直处于一种刷新的状态
动规五部曲
1)确定dp数组的定义
在一维dp数组中,dp[j]表示:容量为j的背包,所背的物品价值可以最大为dp[j]。
2)一维dp数组的递推公式
dp[j]有两个选择,一个是不放物品i,取自己dp[j] 相当于 二维dp数组中的dp[i-1][j];一个是放物品i,取dp[j - weight[i]] + value[i],取二者当中的最大值
dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
3)一维dp数组的初始化
dp[0]就应该是0,因为背包容量为0所背的物品的最大价值就是0。
除了下标0的位置,初始为0,其他下标应该初始化多少呢?
根据递推公式,dp数组在推导的时候一定是取价值最大的数,那么非0下标都初始化为0就可以了,这样才能让dp数组在递归公式的过程中取的最大的价值,而不是被初始值覆盖了。
4)一维dp数组的遍历顺序
一维dp遍历的时候,背包是从大到小,注意一定要是倒序遍历
倒序遍历是为了保证物品i只被放入一次!。但如果一旦正序遍历了,那么物品0就会被重复加入多次!
因为根据递推公式,每个物品只放一次,在遍历物品的时候,变动j时,每次都要刷新dp[j]
dp[1]=dp[1-weight[0]]+value[0]=dp[0]+15=0+15=15
dp[2]=dp[2-weight[0]]+value[0]=dp[1]+value[0]=15+15=30,这里物品0会放入两次,因为前面刷新了dp[1],初始值会被修改,连带着后面的dp[2]会受到波及!!!!
为什么二维dp数组遍历的时候不用倒序呢?
因为对于二维dp,dp[i][j]都是通过上一层即dp[i - 1][j]计算而来,本层的dp[i][j]并不会被覆盖!,因为是二维数组,没有动态刷新,所以一旦求出数值,便会一直在那保持不变
两个嵌套for循环的顺序,代码中是先遍历物品嵌套遍历背包容量,那可不可以先遍历背包容量嵌套遍历物品呢?
不可以!因为一维dp的写法,背包容量一定是要倒序遍历(原因上面已经写了),如果遍历背包容量放在上一层,那么每个dp[j]就只会放入一个物品,即:背包里只放入了一个物品。
因为是每次只对一个背包容量进行求解,
dp[4]=dp[4-1]+value[0]=15
dp[4]=max(15,dp[4-3]+value[1])=max(15,20)=20
dp[4]=max(10,dp[4-4]+value(2))=max(20,30)=30
dp[3]=dp[3-1]+value(0)=value(0)=15
........
如上,因为是倒序遍历和初始化的存在,针对每个背包容量,每次都只放进了一个物品,不能将两个或多个物品的情况考虑在内
dp[4]=dp[4-1]+value[0]=15
dp[3]=max(dp[3],dp[3-1]+value[0])=15
dp[2]=max(dp[2],dp[2-1]+value[0])=15
dp[1]=max(dp[1],dp[1-1]+value[0])=15
dp[4]=max(dp[4],dp[4-3]+value[1])=max(15,15+20)=35
.........
如上,每个背包的容量随着物品的变动与前面每一个物品的情况结合起来,这才是正解
倒序遍历的原因是,本质上还是一个对二维数组的遍历,并且右下角的值依赖上一层左上角的值,因此需要保证左边的值仍然是上一层的,从右向左覆盖。
倾向于使用一维dp数组的写法,比较直观简洁,而且空间复杂度还降了一个数量级!
代码
int weightvalue(int bagweight,vector<int>weight,vector<int>value){//初始化dp数组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]);}}return dp[bagweight];
}
背包问题应用1
题目:416分割等和子集
题目链接:分割等和子集
对题目的理解
非空数组由正整数组成,是否可以将这个数组分割成两个子集,使得两个子集的元素和相等
将问题具象化:只要找到集合里能够出现 sum / 2 的子集总和,就算是可以分割成两个相同元素和子集了。
集合中的元素只能使用一次,因此使用的是01背包
只有确定了如下四点,才能把01背包问题套到本题上来。
- 背包的容量为sum / 2
- 背包要放入的商品(集合里的元素)重量为nums[i],价值也为nums[i]
- 背包如果正好装满,说明找到了总和为 sum / 2 的子集。
- 背包中每一个元素是不可重复放入

动规五部曲
1)确定dp数组含义及下标
dp[j]:容量为j的背包所背的最大价值为dp[j]
集合中的每个元素既是重量也是价值 dp[target]==target 背包装满 其中target=sum/2
2)递推公式
背包的递推公式:dp[j]=max(dp[j],dp[j-weight[i]]+value[i])
所以本题的递推公式:dp[j]=max(dp[j],dp[j-nums[i]]+nums[i])
3)dp数组初始化
dp[0]=0 ,非零下标进行初始化,dp[i]=0,根据递推公式,不能初始化别的值,初始化为非负整数的最小值,即0,这样才能让dp数组在递推的过程中取得最大的价值,而不是被初始值覆盖了。
4)遍历顺序
遍历顺序:先正序遍历物品,后倒序遍历背包容量
for(i=0;i<nums.size(i++)){
for(j=target;j>=nums[i];j--)}
5)打印dp数组
代码
class Solution {
public:bool canPartition(vector<int>& nums) {vector<int> dp(10001,0);//定义dp数组,并将其初始化为0,因为数组中的元素最大是100,且至少有200个数那么最大的重量为200*100=20000,背包中只有一半容量就可以了int sum = 0;for(int i=0;i<nums.size();i++){sum += nums[i];}if(sum % 2==1) return false;//如果和的一半是奇数,那么不可能有两个子集和相等int target = sum/2;//递推公式//先正序遍历物品,后倒序遍历背包for(int i=0;i<nums.size();i++){for(int j=target;j>=nums[i];j--){dp[j]=max(dp[j],dp[j-nums[i]]+nums[i]);}}if(dp[target]==target) return true;return false;}
};
- 时间复杂度:O(n^2)
- 空间复杂度:O(n),虽然dp数组大小为一个常数,但是大常数
相关文章:
C++ day42背包理论基础01 + 滚动数组
背包问题的重中之重是01背包 01背包 有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。 每一件物品其实只有两个状态,取或者不…...
数字人透明屏幕是如何工作的?
数字人透明屏幕是一种令人兴奋的科技产品,它结合了人脸识别、全息影像技术以及透明屏幕,为人们带来了全新的互动体验。本文将详细介绍数字人透明屏幕的工作原理以及其应用场景。 工作原理 数字人透明屏幕的工作原理主要包括人脸识别和全息影像技术。人脸…...
MIGO收货报替代“ZF002“, 步骤““ 中存在语法错误消息号 GB032错误
MIGO收货报替代"ZF002", 步骤"" 中存在语法错误消息号 GB032错误。替代"ZF002", 步骤"" 中存在语法错误消息号 GB032诊断 在 ABAP 代码生成过程中,在替代ZF002中发现了语法错误。 系统响应 未为该布尔陈述生成 ABAP 代码&…...
Vue3的transition标签以及animate.css使用详解
一:前言 在项目开发中,有一种特殊情况是使用动画过渡去完成某个效果。比如淡入淡出,或者在动画完成后执行某些操作等。在以前开发中我们通常会选择使用 CSS3 进行研发。但是这样会有很多不好的地方,比如最原始化的封装,…...
IDEA不支持Java8了怎么办?
IDEA不支持Java8了怎么办? 01 异常发生场景 当我准备创建一个springboot项目时,发现Java8没了 02 问题的产生及其原因 查阅了官方文档之后,确认了是Spring Boot 不再支持 Java 8,不是我的问题,这一天终于还是来了 0…...
flutter的TextField参数、案例整理(上)
TextField 概述 TextField 用于文本输入 构造函数 const TextField({Key key,this.controller, this.focusNode,this.decoration const InputDecoration(),TextInputType keyboardType,this.textInputAction,this.textCapitalization TextCapitalization.none,this.style…...
【Linux进阶之路】进程间通信
文章目录 一、原理二、方式1.管道1.1匿名管道1.1.1通信原理1.1.2接口使用 1.2命名管道 2.共享内存2.1原理2.2接口使用 3.消息队列原理 4.信号量引入原理 总结 一、原理 进程间的通信是什么?解释: 简单理解就是,不同进程之间进行数据的输入输出…...
深度学习框架配置
目录 1. 配置cuda环境 1.1. 安装cuda和cudnn 1.1.1. 显卡驱动配置 1.1.2. 下载安装cuda 1.1.3. 下载cudnn,将解压后文件复制到cuda目录下 1.2. 验证是否安装成功 2. 配置conda环境 2.1. 安装anaconda 2.2. conda换源 2.3. 创建conda环境 2.4. pip换源 3.…...
全局配置
1.全局配置文件及其配置项 1.1.小程序窗口 1.2 窗口节点 1.2.1 导航栏标题 标题: 标题颜色: 背景色:只支持16进制值 下拉刷新: 刷新背景色: 刷新样式: 触底距离:...
leetcode算法之字符串
目录 1.最长公共前缀2.最长回文子串3.二进制求和4.字符串相乘 1.最长公共前缀 最长公共前缀 class Solution { public:string longestCommonPrefix(vector<string>& strs) {//法一:两两比较string ret strs[0];for(int i1;i<strs.size();i){ret f…...
mongodb查询数据库集合的基础命令
基础命令 启动mongo服务 mongod -f /usr/local/mongodb/mongod.conf //注意配置文件路径停止mongo服务 关闭mongodb有三种方式: 一种是进入mongo后通过mongo的函数关闭; use admin db.shutdownServer()一种是通过mongod关闭; mongod --s…...
基于FactoryBean、实例工厂、静态工厂创建Spring中的复杂对象
😉😉 学习交流群: ✅✅1:这是孙哥suns给大家的福利! ✨✨2:我们免费分享Netty、Dubbo、k8s、Mybatis、Spring...应用和源码级别的视频资料 🥭🥭3:QQ群:583783…...
Android 如何让路由器或者其他AP设备获取到主机名
问题原因: 连接到AP设备后,发现主机名在路由器或者其他AP设备都无法正常显示 抓取tcpdump log发现DHCP request option中没有携带host name(Option 12)字段 如下图所示 修改方法: 将config_dhcp_client_hostname配置true后,可以看到host name了 具体代码逻辑如下 pack…...
java三大集合类--List
List Set Map 一、List 几个小问题: 1、接口可以被继承吗?(可以) 2、接口可以被多个类实现吗?(可以) 3、以下两种写法有什么区别? //List list1new List();是错误的因为List()…...
机器人向前冲
欢迎来到程序小院 机器人向前冲 玩法:一直走动的机器人,点击鼠标左键进行跳跃,跳过不同的匝道,掉下去即为游戏接续, 碰到匝道铁钉游戏结束,一直往前冲吧^^。开始游戏https://www.ormcc.com/play/gameStart…...
jq——实现弹幕滚动(往左滚动+往右滚动)——基础积累
最近同事在写弹幕功能,下面记录以下代码: 1.html代码 <div id"scrollContainer"></div>2.引入jq <script src"./script/jquery-1.8.3.js" type"text/javascript"></script>3.jq代码——往左滚…...
深度学习第2天:RNN循环神经网络
☁️主页 Nowl 🔥专栏《机器学习实战》 《机器学习》 📑君子坐而论道,少年起而行之 文章目录 介绍 记忆功能对比展现 任务描述 导入库 处理数据 前馈神经网络 循环神经网络 编译与训练模型 模型预测 可能的问题 梯度消失 梯…...
深度学习之基于百度飞桨PaddleOCR图像字符检测识别系统
欢迎大家点赞、收藏、关注、评论啦 ,由于篇幅有限,只展示了部分核心代码。 文章目录 一项目简介主要特点使用步骤 二、功能三、系统四. 总结 一项目简介 # Introduction to PaddleOCR Image Character Detection and Recognition System Based on Baidu…...
九、LuaTable(表)
文章目录 一、定义二、Table(表)的构造三、Table 操作(一)Table连接(二)插入和移除(三)Table 排序(四)Table 最大值 一、定义 table 是 Lua 的一种数据结构用来帮助我们创建不同的数…...
每日一题(LeetCode)----链表--链表最大孪生和
每日一题(LeetCode)----链表–链表最大孪生和 1.题目(2130. 链表最大孪生和) 在一个大小为 n 且 n 为 偶数 的链表中,对于 0 < i < (n / 2) - 1 的 i ,第 i 个节点(下标从 0 开始)的孪生节点为第 (n…...
51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...
《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...
成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...
python执行测试用例,allure报乱码且未成功生成报告
allure执行测试用例时显示乱码:‘allure’ �����ڲ����ⲿ���Ҳ���ǿ�&am…...
CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!
本文介绍了一种名为AnomalyAny的创新框架,该方法利用Stable Diffusion的强大生成能力,仅需单个正常样本和文本描述,即可生成逼真且多样化的异常样本,有效解决了视觉异常检测中异常样本稀缺的难题,为工业质检、医疗影像…...
DBLP数据库是什么?
DBLP(Digital Bibliography & Library Project)Computer Science Bibliography是全球著名的计算机科学出版物的开放书目数据库。DBLP所收录的期刊和会议论文质量较高,数据库文献更新速度很快,很好地反映了国际计算机科学学术研…...
简单介绍C++中 string与wstring
在C中,string和wstring是两种用于处理不同字符编码的字符串类型,分别基于char和wchar_t字符类型。以下是它们的详细说明和对比: 1. 基础定义 string 类型:std::string 字符类型:char(通常为8位)…...
【Vue】scoped+组件通信+props校验
【scoped作用及原理】 【作用】 默认写在组件中style的样式会全局生效, 因此很容易造成多个组件之间的样式冲突问题 故而可以给组件加上scoped 属性, 令样式只作用于当前组件的标签 作用:防止不同vue组件样式污染 【原理】 给组件加上scoped 属性后…...
IP选择注意事项
IP选择注意事项 MTP、FTP、EFUSE、EMEMORY选择时,需要考虑以下参数,然后确定后选择IP。 容量工作电压范围温度范围擦除、烧写速度/耗时读取所有bit的时间待机功耗擦写、烧写功耗面积所需要的mask layer...
