当前位置:网站首页>背包理论之01背包
背包理论之01背包
2022-08-07 07:35:00 【empty__barrel】
对于面试的话,其实掌握01背包,和完全背包,就够用了,最多可以再来一个多重背包。
背包问题有背包九讲即九个种类的问题
总括:
背包问题即 将n个物品放入容量为 j 的背包中所产生的最大价值。
这个使用动态规划即当前值可由前面值表现出来,具体通过是否将最后一个物品放入到背包中。若放入到背包中此时所产生的最大价值为 前n-1个物品放入到容量为j-weight【n】的背包中所产生的最大价值+第n个物品的价值。若不将最后一个物品放入到背包中,那么此时所产生的最大价值为前n-1个物品放入到容量为 j 的背包中所产生的最大价值。
物品分为:
- 价值
- 体积 / 质量
- 每个物品的数量
01背包应用方面的题目转化为01背包问题。
一:dp数组的含义
dp[i][j]:将第0到 i 个物品放进容量为 j 背包中的最大价值。
二:动态规划所需要的递归公式
通过动态规划的含义即当前值可由前一个值推导出,此时就可以联想到,通过是否将最后一个物品添加到背包中进而实现递归公式。
那么可以有两个方向推出来dp[i][j]即是否将最后一个物品加入到背包中,分为:
- 不放物品i:dp[ i ][ j ]即:将前 i-1个物品放入大小为 j 的背包中的最大价值。
- 具体由dp[i - 1][j]推出,即背包容量为j,里面不放物品i的最大价值,此时dp[i][j]就是dp[i - 1][j]。(其实就是当物品i的重量大于背包j的重量时,物品i无法放进背包中,所以被背包内的价值依然和前面相同。)
- 放物品i:dp[ i ][ j ]即:将前 i-1个物品放入大小为 j -weight[ i ]的背包中的价值加上第 i 个物品的价值。
- 具体由dp[i - 1][j - weight[i]]推出,dp[i - 1][j - weight[i]] 为背包容量为j - weight[i]的时候不放物品i的最大价值,那么dp[i - 1][j - weight[i]] + value[i] (物品i的价值),就是背包放物品i得到的最大价值
所以递归公式: dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
其中在遍历 j 的过程当中需要比较 j 与weight【i】的大小关系
三:dp数组初始化记住图片初始化即可
通过递归公式来判断应该怎样初始化才能达成目的。
i 为物品编号,j 为背包重量,对应图如下:
- 由递推公式可知,当前值是由dp[i - 1][j]和dp[i - 1][j - weight[i]] 决定的。
- i 由 i-1 推导出来的,那么当 i -1不越界时即 i = 1即dp【0】,即要知道dp【0】【0~n】所以要初始化dp【0】【0 ~ n】。
- j 由 j 和 j-weight【i】推导出来,当j-weight【i】不越界时即j-weight【i】 = 0。即dp【0~n】【0】要初始化。

2的实现即 i 为0, j 为0~n:将第0个物品放进容量为 j 背包中的最大价值。
for (int j = 0 ; j < weight[0]; j++) {
// 当然这一步,如果把dp数组预先初始化为0了,这一步就可以省略,但很多同学应该没有想清楚这一点。
dp[0][j] = 0;
}
for (int j = weight[0]; j <= bagweight; j++) {
dp[0][j] = value[0];
}
3的实现即i为0~n,j 为0:将第0 ~n个物品放进容量为0背包中的最大价值(自然是0)
代码省略。
实现2,3的代码:
首先全部初始化为0,然后将实现2,3过程中不应该赋值为0的重新赋值,即如图的部分。
vector<vector<int>> dp(weight.size(), vector<int>(bagweight + 1, 0));
for (int j = weight[0]; j <= bagweight; j++) {
dp[0][j] = value[0];
}
四:确定遍历顺序:怎样来实现当前值的前一个值始终已知。其中在遍历 j 的过程当中需要比较 j 与weight【i】的大小关系
由递归公式可知,从图中看来当前值由上方一个值和左上方一个值来决定。可以举例想象一下遍历过程,然后知道既可以一行一行的遍历,在某一行中从前到后遍历,然后再遍历下一行。也可以一列一列的遍历,在某一行中从上到下遍历,然后再遍历下一列。
j为0的时候不论i为多少价值不都是0吗?为什么还要遍历?
先遍历背包,再遍历物品即纵向遍历 j 递增(此为图形理解并非按照for循环的顺序理解)的代码:
// weight数组的大小 就是物品个数
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]);
}
}
先遍历物品,然后遍历背包重量即横向遍历 i 递增(此为图形理解并非按照for循环的顺序理解)的代码:
// weight数组的大小 就是物品个数
for(int j = 0; j <= bagweight; j++) {
// 遍历背包容量
for(int i = 1; i < weight.size(); i++) {
// 遍历物品
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]);
}
}
完整c++测试代码
void test_2_wei_bag_problem1() {
vector<int> weight = {
1, 3, 4};
vector<int> value = {
15, 20, 30};
int bagweight = 4;
// 二维数组
vector<vector<int>> dp(weight.size(), vector<int>(bagweight + 1, 0));
// 初始化
for (int j = weight[0]; j <= bagweight; j++) {
dp[0][j] = value[0];
}
// weight数组的大小 就是物品个数
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]);
}
}
cout << dp[weight.size() - 1][bagweight] << endl;
}
int main() {
test_2_wei_bag_problem1();
}
边栏推荐
- Shell编程之循环语句
- jenkins配置自动打包
- 8 月数据库排行榜:Oracle 分数大跌,MySQL 上涨最多
- VoLTE Basic Self-Learning Series | VoLTE Network Architecture
- The third bullet of FPGA development: button control LED experiment
- leetcode 110. Balanced Binary Trees
- VoLTE Basic Self-Learning Series | Enterprise Voice Network Brief
- 网络安全笔记4——消息认证与杂凑函数
- The PG function generates the corresponding table creation statement according to the table name
- FPGA开发第三弹:按键控制LED实验
猜你喜欢

LeetCode 628. Maximum Product of Three Numbers

31. Understand what is avalanche, penetration and breakdown of redis?What happens after redis crashes?What are the countermeasures

HPC Technology: Analysis of MPICH Implementation Principle

Why Move will overtake Solidity as the mainstream programming language?

曾“伪造”Solana七成TVL的“多重人格者”,正望向Aptos

【Promise】Promise 使用 / 回调地狱问题 async-await /宏队列与微队列

基于miniprogram-ci的微信小程序的CI以及接入钉钉通知

好消息|Erda 加入中国开源社区 landscape

U-Net网络

Graphical LeetCode - 1408. String Matching in Arrays (Difficulty: Easy)
随机推荐
什么值得买面试题(一)
The third bullet of FPGA development: button control LED experiment
[Promise] Promise use / callback hell problem async-await / macro queue and micro queue
Are there MCUs with 5nm process technology?
LNK2001 unresolved external symbol cuGetErrorName resolved
Recursion: Understanding and Applying
图解LeetCode——1408. 数组中的字符串匹配(难度:简单)
网络安全笔记2——单钥密码体制
VoLTE Basic Self-Learning Series | Which scenarios will trigger CSFB on VoLTE terminals?
传输层(UDP协议,TCP协议三次握手、四次挥手)
信号工必备基础100问【转自微信公众号铁路信号技术交流】
VoLTE Basic Self-Learning Series | IMS Network Overview
面试官:如果要存 IP 地址,用什么数据类型比较好?很多人都会答错
The second bullet of FPGA development: running water lamp experiment
排序--选择排序
Comparison and summary of the four methods of DOM, SAX, JDOM, and DOM4J
PG 函数,根据表名生成对应的建表语句
31. Understand what is avalanche, penetration and breakdown of redis?What happens after redis crashes?What are the countermeasures
day3-文献学习Clustering by fast search and find of density peaks
详解深拷贝,浅拷贝