动态规划/背包问题总结/小结——01背包、完全背包
文章目录
- 前言
- 动态规划五步法
- 01背包模型
- 完全背包
- 总结
前言
背包问题也属于动态规划问题。
动态规划就是将复杂的大问题转化为一个小问题,然后将小问题转化为更小的容易求解的问题;通过将最小的容易求解的问题求解,进而一步步推导、求解出最后的结果。
背包问题分类:
动态规划五步法
- 确定dp数组的含义
- 确定递推公式
- 确定初始值
- 确定遍历顺序
- 手动推导dp数组的值,是否和程序结果一直
01背包模型
背包的容量为15kg,物品0~4的重量和价值分别为如图所示。
问背包能背的物品最大价值是多少?
项目 | Value | Weight |
---|---|---|
物品0 | $4 | 12kg |
物品1 | $2 | 1kg |
物品2 | $10 | 4kg |
物品3 | $1 | 1kg |
物品4 | $2 | 2kg |
每一件物品其实只有两个状态,取或者不取,那么暴力法时间复杂度为O(2^n)。
1. 确定dp数组的含义
dp[i][j],当背包容量为j时,前 i+1 个物品参与放入背包,此时背包能背的物品的最大价值
2. 确定递推公式
背包容量是个常量。当物品 i 不放入背包时 dp[i][j] = dp[i-1][j];当物品 i 放入背包时dp[i][i] = dp[i-1][j-wi] + vi;
所以 dp[i][j] = max( dp[i-1][j], dp[i-1][j-wi]+vi )
3. 确定初始值
根据递推公式,需要确定i=0和j=0时的初值
4. 确定遍历顺序
根据5,本题对遍历顺序没有特别的要求
5. dp数组
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
物品0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 4 | 4 | 4 | 4 |
物品1 | 0 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 4 | 6 | 6 | 6 |
物品2 | 0 | 2 | 2 | 2 | 10 | 12 | 12 | 12 | 12 | 12 | 12 | 12 | 12 | 12 | 12 | 12 |
物品3 | 0 | 2 | 3 | 3 | 10 | 12 | 13 | 13 | 13 | 13 | 13 | 13 | 13 | 13 | 13 | 13 |
物品4 | 0 | 2 | 3 | 4 | 10 | 12 | 13 | 14 | 15 | 15 | 15 | 15 | 15 | 15 | 15 | 15 |
程序示例
vector<int> w = {12,1,4,1,2};vector<int> v = {4,2,10,1,2};int begWight = 15;vector<vector<int>> dp(w.size(), vector<int>(begWight+1, 0));for (int j=0;j<=begWight; ++j){ //dp数组初始化if (w[0] <= j){dp[0][j] = v[0];}}//根据递推公式计算dpfor (int i=1; i<w.size(); ++i){for (int j=1; j<=begWight; ++j){if (j<w[i]) dp[i][j] = dp[i-1][j];else dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]]+v[i]);}}//打印dpfor (int i=0; i<dp.size(); ++i){for (int j=0; j<dp[0].size(); ++j){cout << dp[i][j] << " ";}cout << endl;}
优化dp的维度
- 根据递推公式dp[i][j] = max( dp[i-1][j], dp[i-1][j-wi]+vi ),i取决于i-1,所以可以降二维dp降为一维度。
此时dp[j]的含义为容量为j的背包能背物品的最大价值。 - 递推公式变为:dp[j] = max(dp[j], dp[j-wi]+vi)
- dp数组初始化,全都为0就行
- 遍历顺序就有了要求,物品i在外部循环,背包的容量j在内部循环。j从大到小
for (int i=0; i<w.size(); ++i){ //先遍历物品for (int j=begWight; j>=w[i]; --j){ //再遍历背包dp[j] = max(dp[j], dp[j-w[i]]+v[i]);}
}
- dp数组
当i=0; dp 0 0 0 0 0 0 0 0 0 0 0 0 4 4 4 4
当i=1; dp 0 2 2 2 2 2 2 2 2 2 2 2 4 6 6 6
当i=2; dp 0 2 2 2 10 12 12 12 12 12 12 12 12 12 12 12
当i=3; dp 0 2 3 3 10 12 13 13 13 13 13 13 13 13 13 13
当i=4; dp 0 2 3 4 10 12 13 14 15 15 15 15 15 15 15 15
代码示例
vector<int > dp(begWight+1, 0);// 以下for循环的遍历顺序及j的顺序不能变,思考如果变了会怎么样for (int i=0; i<w.size(); ++i){ //先遍历物品for (int j=begWight; j>=w[i]; --j){ //再遍历背包,从大到小dp[j] = max(dp[j], dp[j-w[i]]+v[i]);}}for (auto c:dp){cout << c<< " ";}
备注
关于4.一维dp数组的遍历顺序大有讲究,可仔细研究。
当先遍历背包后遍历物品时(j从大到小,i从小到大),每个dp[j]就只会放入一个物品。
当先遍历物品再遍历背包(i从小到大,j从小到大),dp[j]中同一个物品会被放入多次,不符合01背包原则。
完全背包
有N件物品和一个最多能背重量为W的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品都有无限个(也就是可以放入背包多次),求解将哪些物品装入背包里物品价值总和最大。
完全背包和01背包问题唯一不同的地方就是,每种物品有无限件。
例如:
W | V | |
---|---|---|
物品0 | 1 | 15 |
物品1 | 3 | 20 |
物品2 | 4 | 30 |
- dp[j]代表容量为j的背包能背物品的最大价值
- dp[j] = max(dp[j], dp[j-wi]+vi)
- 对于此题初始化为0就好
- 对于遍历顺序可小讨论下。完全背包就是物品可重复放入背包,因此遍历顺序为先遍历物品(i有小到大),再遍历背包(j由小到大)。
其实,先遍历背包再遍历物品也可。 - 略
程序示例
vector<int> weight = {1, 3, 4};vector<int> value = {15, 20, 30};int bagWeight = 4;vector<int> dp(bagWeight + 1, 0);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]);}}
总结
01背包模型是所有背包问题的基础。后面的完全背包,多重背包,都是在透彻理解01背包之后的进一步分析,理解了01背包,完全背包、多重背包就非常容易理解。
递推公式:
背包总价值:dp[j] = max(dp[j], dp[j - w[i]] + v[i])
装满背包:dp[j] += dp[j - nums[i]]
遍历顺序:
01背包 | 完全背包 | |
---|---|---|
顺序问题 | 只有这一种顺序,先遍历物品(由到大)再遍历背包(有大到小) | 先遍历物品(由小到大)再遍历背包(有小到大),其实反过来也行 |
动态规划/背包问题总结/小结——01背包、完全背包相关推荐
- 动态规划——背包问题整理(01背包+完全背包)
1.引言 背包问题简单描述,其实就是有一堆物品同时具有一定价值和重量,现有一个背包可以承受最大重量m,那么要怎么选择在不超过背包最大重量的前提下,使背包中选择的物品价值最大. 最常见的背包问题又可以分 ...
- 动态规划 背包问题小结 0-1背包(采药 九度第101题) 完全背包(Piggy-Bank POJ 1384) 多重背包(珍惜现在,感恩生活 九度第103题)
本小结介绍0-1背包.完全背包以及多重背包问题 记忆要点: 0-1背包:二维数组情况下,顺序遍历体积或者倒序均可以 降维情况下需倒序遍历体积 完全背包:数组降维+顺序遍历 ...
- 动态规划背包问题之01背包详解
文章目录 一.问题引入 1.什么是动态规划? 2.什么是背包问题? 3.什么是01背包? 4.背包问题怎么做? 二.例题讲解 1.题目: 2.分析 2.1 第一步:状态表示 2.2 第二步:确定状态转 ...
- 动态规划_背包问题(01背包 完全背包)
背包问题-多种物品 重量不同 价值不同. 你可以取最多重量不超过W的物品,问最大价值为多少? 01背包 01背包 指的是 有N个物品 每个物品的重量为W[ i ],价值为V[ i ],(每个物品只有一 ...
- 动态规划背包问题——01背包
2022.7.20 题意概要:有n个物品和一个容量为p的背包,每个物品有重量w和价值v两种属性,要求选若干物品放入背包使背包中物品的总价值最大且背包中物品的总重量不超过背包的容量. 在 ...
- 动态规划总结(01背包 完全背包 多重背包)
动态规划总结(01背包 完全背包 多重背包) 一.学习资料 1.UVA DP 入门专题 2.夜深人静写算法(二) - 动态规划 3.算法之动态规划 4.什么是动态规划?动态规划的意义是什么? 5.01 ...
- 完全背包问题+01背包问题+分组背包+多重背包 总结
背包问题都涉及到动态规划,利用dp进行更加优化的计算. 一.01背包 最基本的是01背包问题,题目一般类似:"在一定数目物品内,挑选总重量不超过一定数目的物品,其中每个物品只能选一次,求背包 ...
- 经典背包问题 01背包+完全背包+多重背包
01 背包 有n 种不同的物品,每个物品有两个属性,size 体积,value 价值,现在给一个容量为 w 的背包,问最多可带走多少价值的物品. int f[w+1]; //f[x] 表示背包容量为x ...
- Java入门算法(动态规划篇2:01背包精讲)
本专栏已参加蓄力计划,感谢读者支持❤ 往期文章 一. Java入门算法(贪心篇)丨蓄力计划 二. Java入门算法(暴力篇)丨蓄力计划 三. Java入门算法(排序篇)丨蓄力计划 四. Java入门算 ...
最新文章
- Ubuntu中安装docker-compose
- MySQL查询一周借阅最多的书_SQL中的借书经典案例
- AtCoder AGC032E Modulo Pairing (二分、贪心结论)
- 某信道的波特率为1000Baud,若令其数据传输速率达到4kb/s,则一个信号码元所取的有效离散值个数为( )
- 5学习周报_你做好周报的“闭环管理”了吗?——“周报管理知多少”
- 常见的网上邻居访问问题
- jdk版本 linux更改was_如何在 Linux 上安装 Java
- linux ps 代码,Linux ps命令详解(示例代码)
- three.js script vertex和fragment在react中使用/纯js写法
- 信息学奥赛一本通C++语言——1124:矩阵加法
- 牛客练习赛23: D. 托米的咒语(暴力)
- matlab 流星雨,dijkstra算法及其matlab实现
- nyoj--38--布线问题
- 为什么不要把ZooKeeper用于服务发现
- linux 创建用户_用 Bash 脚本发送新用户帐户创建的邮件 | Linux 中国
- 我与希赛PMP的不解之缘
- PSCAD中的频变参数线路模型(Frequency-Dependent (Phase) Line Model)
- 服务端开发or客户端开发的选择
- Linux权限详解(chmod 777)
- Win10--在右键菜单中添加cmd.exe(在此处打开CMD窗口)