This commit is contained in:
programmercarl
2024-08-29 20:39:18 +08:00
parent 1609759238
commit 574cef48b3
30 changed files with 1686 additions and 236 deletions

View File

@@ -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表示背包容量。
![](https://code-thinking-1253855093.file.myqcloud.com/pics/20240730174246.png)
如果放物品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 的价值,推导方向如图:
![](https://code-thinking-1253855093.file.myqcloud.com/pics/20240730174436.png)
两种情况分别是放物品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. 确定遍历顺序
在如下图中,可以看出,有两个遍历的维度:物品与背包重量
![动态规划-背包问题3](https://code-thinking-1253855093.file.myqcloud.com/pics/2021011010314055.png)
@@ -364,7 +366,6 @@ int main() {
## 其他语言版本
### Java