Update
This commit is contained in:
@@ -29,7 +29,7 @@
|
||||
|
||||
而完全背包又是也是01背包稍作变化而来,即:完全背包的物品数量是无限的。
|
||||
|
||||
**所以背包问题的理论基础重中之重是01背包,一定要理解透!**
|
||||
**所以背包问题的理论基础重中之重是01背包,一定要理解透**!
|
||||
|
||||
leetcode上没有纯01背包的问题,都是01背包应用方面的题目,也就是需要转化为01背包问题。
|
||||
|
||||
@@ -67,6 +67,7 @@ leetcode上没有纯01背包的问题,都是01背包应用方面的题目,
|
||||
|
||||
以下讲解和图示中出现的数字都是以这个例子为例。
|
||||
|
||||
(为了方便表述,下面描述 统一用 容量为XX的背包,放下容量(重量)为XX的物品,物品的价值是XX)
|
||||
|
||||
### 二维dp数组01背包
|
||||
|
||||
@@ -76,7 +77,7 @@ leetcode上没有纯01背包的问题,都是01背包应用方面的题目,
|
||||
|
||||
我们需要使用二维数组,为什么呢?
|
||||
|
||||
因为有两个维度需要表示,分别是:物品 和 背包容量
|
||||
因为有两个维度需要分别表示:物品 和 背包容量
|
||||
|
||||
如图,二维数组为 dp[i][j]。
|
||||
|
||||
@@ -110,13 +111,13 @@ i 来表示物品、j表示背包容量。
|
||||
|
||||
背包容量为 0,放不下物品0 或者物品1,此时背包里的价值为0。
|
||||
|
||||
背包容量为 1,只能放下物品1,背包里的价值为15。
|
||||
背包容量为 1,只能放下物品0,背包里的价值为15。
|
||||
|
||||
背包容量为 2,只能放下物品1,背包里的价值为15。
|
||||
背包容量为 2,只能放下物品0,背包里的价值为15。
|
||||
|
||||
背包容量为 3,上一行同一状态,背包只能放物品0,这次也可以选择物品1了,背包可以放物品2 或者 物品1,物品2价值更大,背包里的价值为20。
|
||||
背包容量为 3,上一行同一状态,背包只能放物品0,这次也可以选择物品1了,背包可以放物品1 或者 物品0,物品1价值更大,背包里的价值为20。
|
||||
|
||||
背包容量为 4,上一行同一状态,背包只能放物品0,这次也可以选择物品1了,背包都可都放下,背包价值为35。
|
||||
背包容量为 4,上一行同一状态,背包只能放物品0,这次也可以选择物品1了,背包可以放下物品0 和 物品1,背包价值为35。
|
||||
|
||||
以上举例,是比较容易看懂,我主要是通过这个例子,来帮助大家明确dp数组的含义。
|
||||
|
||||
@@ -144,7 +145,10 @@ i 来表示物品、j表示背包容量。
|
||||
|
||||
这里我们dp[1][4]的状态来举例:
|
||||
|
||||
绝对 dp[1][4],就是放物品1 ,还是不放物品1。
|
||||
求取 dp[1][4] 有两种情况:
|
||||
|
||||
1. 放物品1
|
||||
2. 还是不放物品1
|
||||
|
||||
如果不放物品1, 那么背包的价值应该是 dp[0][4] 即 容量为4的背包,只放物品0的情况。
|
||||
|
||||
@@ -152,24 +156,23 @@ i 来表示物品、j表示背包容量。
|
||||
|
||||

|
||||
|
||||
|
||||
如果放物品1, **那么背包要先留出物品1的容量**,目前容量是4,物品1 需要重量为3,此时背包剩下容量为1。
|
||||
如果放物品1, **那么背包要先留出物品1的容量**,目前容量是4,物品1 的容量(就是物品1的重量)为3,此时背包剩下容量为1。
|
||||
|
||||
容量为1,只考虑放物品0 的最大价值是 dp[0][1],这个值我们之前就计算过。
|
||||
|
||||
所以 放物品1 的情况 = dp[0][1] + 物品1 的重量,推导方向如图:
|
||||
所以 放物品1 的情况 = dp[0][1] + 物品1 的价值,推导方向如图:
|
||||
|
||||

|
||||
|
||||
两种情况,分别是放物品1 和 不放物品1,我们要取最大值(毕竟求的是最大价值)
|
||||
|
||||
`dp[1][4] = max(dp[0][4], dp[0][1] + 物品1 的重量) `
|
||||
`dp[1][4] = max(dp[0][4], dp[0][1] + 物品1 的价值) `
|
||||
|
||||
以上过程,抽象化如下:
|
||||
|
||||
* **不放物品i**:由dp[i - 1][j]推出,即背包容量为j,里面不放物品i的最大价值,此时dp[i][j]就是dp[i - 1][j]。
|
||||
* **不放物品i**:背包容量为j,里面不放物品i的最大价值是dp[i - 1][j]。
|
||||
|
||||
* **放物品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得到的最大价值
|
||||
* **放物品i**:背包空出物品i的容量后,背包容量为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]);`
|
||||
|
||||
@@ -235,7 +238,6 @@ for (int j = weight[0]; j <= bagweight; j++) {
|
||||
|
||||
4. 确定遍历顺序
|
||||
|
||||
|
||||
在如下图中,可以看出,有两个遍历的维度:物品与背包重量
|
||||
|
||||

|
||||
@@ -364,7 +366,6 @@ int main() {
|
||||
|
||||
|
||||
|
||||
|
||||
## 其他语言版本
|
||||
|
||||
### Java
|
||||
|
||||
Reference in New Issue
Block a user