完全背包问题(二维数组 / 一维数组实现)

完全背包

完全背包的一维和二维dp数组

有 N 件物品和容量为 W 的背包,第 i 件物品的重量是 weight[i],价值是 value[i]

每件物品都有无限个,即同一物品能够放入背包多次,求背包所能装入物品的最大价值总和

完全背包和 0-1 背包不同就在于每种物品有无数件,同一物品能够放入背包多次

二维数组实现

// 完全背包问题
// 二维dp数组
// n个物品 背包容量为m
int knapSack(int n, int m, vector<int>& weight, vector<int>& value) {vector<vector<int> dp(n+1, vector<int>(m+1, 0));// dp[i][j]:从前i个物品中选择放入容量为j的背包中得到的最大价值// 注意这种定义,第i件物品的重量为weight[i-1],价值为value[i-1]// dp[i][j] = max(dp[i-1][j], dp[i-1][j-weight[i-1]] + value[i-1])// 初始化// 当j=0时,背包容量为0,最大价值为0;当i=0时,也就是前0件物品,也就是没有物品,最大价值也是0for (int i = 1; i <= n; i++) {for (int j = 1; j <= m; j++) {if (j - weight[i-1] < 0) // 如果当前背包容量放不下第i件物品,那么前i件物品放入背包得到的最大价值就是前i-1件物品放入获得的最大价值dp[i][j] = dp[i-1][j];else { // 如果能放下,从放和不放两种选择里取最大值,这里要注意,其实完全背包二维数组的代码跟一维只有下面一个下标不同,那就是“放i”这个选择,因为是可以重复放的,所以是dp[i]dp[i][j] = max(dp[i-1][j], dp[i][j-weight[i-1]] + value[i-1]);}}}return dp[n][m];
}

完全背包和 0-1 背包二维dp数组的代码只有一个下标不同

两个 for 循环的遍历顺序是可以颠倒的,这跟递归的本质和递推的方向有关系。dp[i][j] = max(dp[i - 1][j], dp[i][j - weight[i-1]] + value[i-1]);递归公式中可以看出 dp[i][j] 是靠dp[i-1][j]和 dp[i][j - weight[i-1]] 推导出来的,他们俩都在dp[i][j]的左上角方向(包括正左和正上两个方向),分析先遍历物品和先遍历背包的过程,在计算dp[i][j]之前都已经得到了,不影响公式的推导

完全背包和 0-1 背包在能够放下物品 i 时的状态转移公式存在区别

// 0-1 背包
dp[i][j] = max(dp[i-1][j], dp[i - 1][j-weight[i-1]] + value[i-1]);// 完全背包
dp[i][j] = max(dp[i-1][j], dp[i][j-weight[i-1]] + value[i-1]);

完全背包由于物品可以重复选取,因此是 dp[i][j-weight[i-1]]

一维数组实现

首先回顾0-1背包的核心代码:

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]);}
}

0-1背包内嵌的循环是从大到小遍历,为了保证每个物品仅被添加一次

完全背包的物品是可以添加多次的,因此要从小到大遍历,即:

// 先遍历物品,再遍历背包
for(int i = 0; i < weight.size(); i++) { // 遍历物品for(int j = weight[i]; j < bagWeight ; j++) { // 遍历背包容量dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);}
}

或者:

// 先遍历背包,再遍历物品
for(int j = 0; j <= bagWeight; j++) { // 遍历背包容量for(int i = 0; i < weight.size(); i++) { // 遍历物品if (j - weight[i] >= 0) dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);}
}

完全背包中,对于一维dp数组来说,其实两个for循环嵌套顺序无所谓

因为dp[j]是根据下标j之前所对应的dp[j]计算出来的,只要保证下标j之前的dp[j]都是经过计算的就可以了(容量的遍历是从小到大遍历,也就是从小到大计算)

在这里插入图片描述

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

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

相关文章

微服务:Springboot集成Hystrix实现熔断、降级、隔离

文章目录 前言知识积累Springboot集成Hystrix1、maven依赖引入2、application开启feign的hystrix支持&#xff08;客户端配置限流降级熔断&#xff09;3、入口类增加EnableFeignClients EnableHystrix 开启feign与hystrix4、feign调用增加降级方法服务端配置限流降级熔断(选择使…

NSS [MoeCTF 2022]ezphp

NSS [MoeCTF 2022]ezphp 先看题目&#xff0c;看到这个就想到了BUU的mark love cat。但是完全不一样&#xff0c;这道题exit()在foreach()之前 法一且唯一&#xff1a; echo回显flag 如果要echo&#xff0c;那么不能exit&#xff0c;那么必须传flag&#xff08;get或者post&a…

【SLAM学习】FAST-LIO配置

本文主要记录如何配置FAST-LIO Eigen库 Eigen库安装&#xff1a; sudo apt install libeigen3-dev 查看Eigen版本&#xff1a; $ pkg-config --modversion eigen3 PCL库 PCL库安装&#xff1a; sudo apt install libpcl-dev 也可以指定版本安装&#xff1a; sudo apt …

Unity 新输入系统InputAction设置按键的阈值

输入阈值问题 在新的输入系统中&#xff0c;如果添加一个手柄按键只需要添加Pressed就够了&#xff0c;监听他的三个动作就可以得到按下&#xff0c;点击&#xff0c;抬起。 例如下面的代码&#xff1a; inputAction.Player.Trigger_Right.started OnRightTriggerStarted;i…

天翎群晖NAS为全文检索插翅起飞

编者按&#xff1a;企业的文档资料随着企业的业务发展会越来越多&#xff0c;想要某个资料的时候&#xff0c;最怕找不到想要的资料&#xff0c;这时KMS的全文检索功能就非常重要了&#xff0c;只需只言片语的零星关键字&#xff0c;查找文档没压力。 关键词&#xff1a;全文检…

【网络原理之一】应用层协议、传输层协议UDP和TCP,TCP的三次握手和四次挥手以及TCP的可靠和效率机制

应用层协议XML协议JSONHTTP 传输层协议UDP协议UDP的特点UDP协议格式 TCP协议TCP的特点TCP协议格式TCP的安全和效率机制确认应答(可靠机制)超时重传(可靠机制)连接管理(可靠机制)三次握手(连接过程)四次挥手(断开的过程)状态的转化 滑动窗口(效率机制)流量控制(可靠机制)拥塞控制…

代码随想录二刷 day38 | 动态规划之 509. 斐波那契数 70. 爬楼梯 746. 使用最小花费爬楼梯

day38 509. 斐波那契数1 确定dp数组以及下标的含义2 确定递推公式3 dp数组如何初始化4 确定遍历顺序5 举例推导dp数组 70. 爬楼梯1 确定dp数组以及下标的含义2 确定递推公式3 dp数组如何初始化4 确定遍历顺序5 举例推导dp数组 746. 使用最小花费爬楼梯1 确定dp数组以及下标的含…

探索Gradio库中的Image模块及其强大功能

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️ &#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

jvm运行时数据区

一、jdk、jre、jvm的关系 jvm只是把class字节码文件翻译成机器识别的二进制数据&#xff0c;不同的操作系统生成的操作系统指令又会不一样jre除了包含jvm外&#xff0c;还提供了很多类库&#xff08;java.io、java.swing等包下类库&#xff09;提供工具&#xff0c;比如javac&a…

MongoDB【MongoDB命令、CRUD操作 】(二)-全面详解(学习总结---从入门到深化)

目录 MongoDB命令 CRUD操作 MongoDB命令 基本操作 查看数据库 show dbs; 切换数据库 如果没有对应的数据库则创建 use 数据库名;创建集合 db.createCollection("集合名") 查看集合 show tables; show collections; 删除集合 db.集合名.drop(); 删除当前…

基于matlab使用深度学习的语义分割算法实现(附源码)

一、前言 此示例演示如何使用语义分割网络对图像进行分割。 语义分割网络对图像中的每个像素进行分类&#xff0c;从而生成按类分割的图像。语义分割的应用包括自动驾驶的道路分割和医疗诊断的癌细胞分割。 此示例首先向您展示如何使用预训练的 Deeplab v3 [1] 网络分割图像&am…

看一眼Mysql查询语句

目录 &#x1f6fb; 查询数据 &#x1f6fb;基本查询语句 &#x1f6fb;单表查询 &#x1f695;查询所有字段 &#x1f695;查询指定字段 &#x1f695;查询指定记录 &#x1f695;带in关键字的查询 &#x1f695;带between and的范围查询 &#x1f695;带like的字符匹…