|
1 | 1 | ## 1. 背包问题简介
|
2 | 2 |
|
3 | | -> **背包问题**:背包问题是线性 DP 问题中一类经典而又特殊的模型。背包问题可以描述为:给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,我们如何选择,才能使得物品的总价格最高。 |
| 3 | +### 1.1 背包问题的定义 |
| 4 | + |
| 5 | +> **背包问题**:背包问题是线性 DP 问题中一类经典而又特殊的模型。背包问题可以描述为:给定一组物品,每种物品都有自己的重量、价格以及数量。再给定一个最多能装重量为 $W$ 的背包。现在选择一些物品放入背包中,请问在总重量不超过背包装载重量上限的情况下,能装入背包的最大价值总合是多少? |
| 6 | + |
| 7 | +根据物品限制条件的不同,背包问题可分为:0-1 背包问题、完全背包问题、多重背包问题、分组背包问题,以及混合背包问题等。 |
| 8 | + |
| 9 | +### 1.2 背包问题的暴力解题思路 |
| 10 | + |
| 11 | +背包问题的暴力解题思路比较简单。假设有 $n$ 件物品。我们先枚举出这 $n$ 件物品所有可能的组合。然后再对这些组合判断是否能放入背包,以及是否能得到最大价值。但是这种做法的时间复杂度是 $O(2^n),ドル其中 $n$ 表示物品数量。 |
| 12 | + |
| 13 | +暴力解法的时间复杂度是指数级别的,但是我们可以利用动态规划算法减少一下时间复杂度。 |
4 | 14 |
|
5 | 15 | ## 2. 0-1 背包问题
|
6 | 16 |
|
7 | | -> **0-1 背包问题**:有 $n$ 件物品和有一个最多能装重量为 $W$ 的背包。第 $i$ 件物品的重量为 $weight[i],ドル价值为 $value[i],ドル每件物品有且只有 1ドル$ 件。请问在总重量不超过背包重量上限的情况下,能装入背包的最大价值是多少? |
| 17 | +> **0-1 背包问题**:有 $n$ 件物品和有一个最多能装重量为 $W$ 的背包。第 $i$ 件物品的重量为 $weight[i],ドル价值为 $value[i],ドル每件物品有且只有 1ドル$ 件。请问在总重量不超过背包装载重量上限的情况下,能装入背包的最大价值是多少? |
8 | 18 |
|
9 | 19 | ### 2.1 0-1 背包问题基本思路
|
10 | 20 |
|
| 21 | +> **0-1 背包问题的特点**:每种物品有且仅有 1ドル$ 件,可以选择放入背包,也可以选择不放入背包。 |
| 22 | + |
| 23 | +#### 思路 1:动态规划 |
| 24 | + |
| 25 | +###### 1. 划分阶段 |
| 26 | + |
| 27 | +按照物品的序号进行阶段划分。 |
| 28 | + |
| 29 | +###### 2. 定义状态 |
| 30 | + |
| 31 | +定义状态 $dp[i][w]$ 表示为:前 $i$ 件物品放入一个最多能装重量为 $w$ 的背包中,可以获得的最大价值。 |
| 32 | + |
| 33 | +状态 $dp[i][w]$ 是一个二维数组,其中第一维代表「当前正在考虑的物品」,第二维表示「当前背包的装载重量上限」,二维数组值表示「可以获得的最大价值」。 |
| 34 | + |
| 35 | +###### 3. 状态转移方程 |
| 36 | + |
| 37 | +对于「将前 $i$ 件物品放入一个最多能装重量为 $w$ 的背包中,可以获得的最大价值 」这个子问题,如果我们只考虑第 $i$ 件物品的放入策略(放入背包和不放入背包两种策略)。则问题可以转换为一个只跟前 $i - 1$ 件物品相关的问题。 |
| 38 | + |
| 39 | +1. **如果第 $i$ 件物品不放入背包**:问题转换为「前 $i - 1$ 件物品放入一个最多能装重量为 $w$ 的背包中 ,可以获得的最大价值为 $dp[i - 1][w]$」。 |
| 40 | +2. **如果第 $i$ 件物品放入背包**:问题转换为「前 $i - 1$ 件物品放入一个最多能装重量为 $w - weight[i]$ 的背包中,可以获得的最大价值为 $dp[i - 1][w - weight[i]]$」」,再加上「放入的第 $i$ 件物品的价值 $value[i]$」,则此时可以获得的最大价值为 $dp[i - 1][w - weight[i]] + value[i]$。 |
| 41 | + |
| 42 | +当然第 $i$ 件物品能够放入背包的前提是:当前背包的装载重量上限 ≥ 第 $i$ 件物品的重量,即 $w \ge weight[i]$。 |
| 43 | + |
| 44 | +则状态转移方程为: |
| 45 | + |
| 46 | +$dp[i][w] = max \begin{cases} dp[i - 1][w] & 第 i 件物品不放入背包 \cr dp[i - 1][w - weight[i]] + value[i] & 第 i 件物品放入背包 \end{cases}$ |
| 47 | + |
| 48 | +###### 4. 初始条件 |
| 49 | + |
| 50 | +- 如果背包容量为 0ドル,ドル则无论选取什么物品,可以获得的最大价值一定是 0ドル,ドル即 $dp[i][0] = 0$。 |
| 51 | +- 前 0ドル$ 件物品所能获得的最大价值一定为 0ドル,ドル即 $dp[0][w] = 0$。 |
| 52 | + |
| 53 | +###### 5. 最终结果 |
| 54 | + |
| 55 | +#### 思路 1:代码 |
| 56 | + |
| 57 | +```Python |
| 58 | +class Solution: |
| 59 | + def zeroOnePack(self, weight: [int], value: [int], W: int): |
| 60 | + size = len(weight) |
| 61 | + dp = [[0 for _ in range(W + 1)] for _ in range(size + 1)] |
| 62 | + |
| 63 | + for i in range(1, size + 1): |
| 64 | + for w in range(weight[i], W + 1): |
| 65 | + dp[i][w] = max(dp[i - 1][w], dp[i - 1][w - weight[i]] + value) |
| 66 | + |
| 67 | + return dp[size] |
| 68 | +``` |
| 69 | + |
| 70 | +#### 思路 1:复杂度分析 |
| 71 | + |
| 72 | +- **时间复杂度**:$O(n \times W),ドル其中 $n$ 为物品数量,$W$ 为背包的装载重量上限。 |
| 73 | +- **空间复杂度**:$O(n \times W)$。 |
| 74 | + |
| 75 | +### 2.2 0-1 背包问题滚动数组优化 |
| 76 | + |
| 77 | + |
| 78 | + |
11 | 79 | ## 3. 完全背包问题
|
12 | 80 |
|
13 | | -> **完全背包问题**:有 $n$ 种物品和一个最多能装重量为 $W$ 的背包,第 $i$ 件物品的重量为 $weight[i],ドル价值为 $value[i],ドル每种物品数量没有限制。请问在总重量不超过背包重量上限的情况下,能装入背包的最大价值是多少? |
| 81 | +> **完全背包问题**:有 $n$ 种物品和一个最多能装重量为 $W$ 的背包,第 $i$ 件物品的重量为 $weight[i],ドル价值为 $value[i],ドル每种物品数量没有限制。请问在总重量不超过背包装载重量上限的情况下,能装入背包的最大价值是多少? |
14 | 82 |
|
15 | 83 | ## 4. 多重背包问题
|
16 | 84 |
|
17 | | -> **多重背包问题**:有 $n$ 种物品和一个最多能装重量为 $W$ 的背包,第 $i$ 种物品的重量为 $weight[i],ドル价值为 $value[i],ドル件数为 $count[i]$。请问在总重量不超过背包重量上限的情况下,能装入背包的最大价值是多少? |
| 85 | +> **多重背包问题**:有 $n$ 种物品和一个最多能装重量为 $W$ 的背包,第 $i$ 种物品的重量为 $weight[i],ドル价值为 $value[i],ドル件数为 $count[i]$。请问在总重量不超过背包装载重量上限的情况下,能装入背包的最大价值是多少? |
| 86 | + |
| 87 | +## 5. 分组背包问题 |
18 | 88 |
|
19 | 89 | ## 参考资料
|
20 | 90 |
|
21 | 91 | - 【资料】[背包九讲 - 崔添翼](https://github.com/tianyicui/pack)
|
| 92 | +- 【文章】[背包 DP - OI Wiki](https://oi-wiki.org/dp/knapsack/) |
0 commit comments