6. 分组背包问题
分组背包问题:有 n 组物品和一个最多能装重量为 W 的背包,第 i 组物品的件数为 groupcount[i],第 i 组的第 j 个物品重量为 weight[i] [j],价值为 value[i] [j]。每组物品中最多只能选择 1 件物品装入背包。请问在总重量不超过背包载重上限的情况下,能装入背包的最大价值是多少?
6.1 分组背包问题基本思路
思路 1:动态规划 + 二维基本思路
- 划分阶段
按照物品种类的序号、当前背包的载重上限进行阶段划分。
- 定义状态
定义状态 dp[i] [w] 表示为:前 i 组物品放入一个最多能装重量为 w 的背包中,可以获得的最大价值。
状态 dp[i] [w] 是一个二维数组,其中第一维代表「当前正在考虑的物品组数」,第二维表示「当前背包的载重上限」,二维数组值表示「可以获得的最大价值」。
- 状态转移方程
- 初始条件
- 如果背包载重上限为 0,则无论选取什么物品,可以获得的最大价值一定是 0,即 dp[i] [0]=0,0≤i≤size。
- 无论背包载重上限是多少,前 0 组物品所能获得的最大价值一定为 0,即 dp[0] [w]=0,0≤w≤W。
- 最终结果
根据我们之前定义的状态,dp[i] [w] 表示为:前 i 组物品放入一个最多能装重量为 w 的背包中,可以获得的最大价值。则最终结果为 dp[size] [W],其中 size 为物品的种类数W 为背包的载重上限。
思路 1:代码
1 | class Solution: |
思路 1:复杂度分析
- 时间复杂度:O(n×W×C),其中 n 为物品分组数量,W 为背包的载重上限,C 是每组物品的数量。因为 n×C=∑groupcount[i],所以时间复杂度也可以写成 O(W×∑groupcount[i])。
- 空间复杂度:O(n×W)。
6.2 分组背包问题滚动数组优化
思路 2:动态规划 + 滚动数组优化
- 划分阶段
按照当前背包的载重上限进行阶段划分。
- 定义状态
定义状态 dp[w] 表示为:将物品装入最多能装重量为 w 的背包中,可以获得的最大价值。
- 状态转移方程
- 初始条件
- 无论背包载重上限为多少,只要不选择物品,可以获得的最大价值一定是 0,即 dp[w]=0,0≤w≤W。
- 最终结果
根据我们之前定义的状态, dp[w] 表示为:将物品装入最多能装重量为 w 的背包中,可以获得的最大价值。则最终结果为 dp[W],其中 W 为背包的载重上限。
思路 2:代码
1 | class Solution: |
思路 2:复杂度分析
- 时间复杂度:O(n×W×C),其中 n 为物品分组数量,W 为背包的载重上限,C 是每组物品的数量。因为 n×C=∑groupcount[i],所以时间复杂度也可以写成 O(W×∑groupcount[i])。
- 空间复杂度:O(W)。
7. 二维费用背包问题
二维费用背包问题:有 n 件物品和有一个最多能装重量为 W、容量为 V 的背包。第 i 件物品的重量为 weight[i],体积为 volume[i],价值为 value[i],每件物品有且只有 1 件。请问在总重量不超过背包载重上限、容量上限的情况下,能装入背包的最大价值是多少?
7.1 二维费用背包问题基本思路
我们可以参考「0-1 背包问题」的状态定义和基本思路,在「0-1 背包问题」基本思路的基础上,增加一个维度用于表示物品的容量。
思路 1:动态规划 + 三维基本思路
- 划分阶段
按照物品种类的序号、当前背包的载重上限、容量上限进行阶段划分
- 定义状态
定义状态 dp[i] [w] [v] 为:前 i 件物品放入一个最多能装重量为 w、容量为 v 的背包中,可以获得的最大价值。
- 状态转移方程
- 初始条件
- 如果背包载重上限为 0 或者容量上限为 0,则无论选取什么物品,可以获得的最大价值一定是 0,即:
- dp[i] [w] [0]=0,0≤i≤size,0≤w≤W
- dp[i] [0] [v]=0,0≤i≤size,0≤v≤V
- 无论背包载重上限是多少,前 0 种物品所能获得的最大价值一定为 0,即:
- dp[0] [w] [v]=0,0≤w≤W,0≤v≤V
- 最终结果
根据我们之前定义的状态, dp[i] [w] [v] 表示为:前 i 件物品放入一个最多能装重量为 w、容量为 v 的背包中,可以获得的最大价值。则最终结果为 dp[size] [W] [V],其中 size 为物品的种类数,W 为背包的载重上限,V 为背包的容量上限。
思路 1:代码
1 | class Solution: |
思路 1:复杂度分析
- 时间复杂度:O(n×W×V),其中 n 为物品分组数量,W 为背包的载重上限,V 为背包的容量上限。
- 空间复杂度:O(n×W×V)。
7.2 二维费用背包问题滚动数组优化
思路 2:动态规划 + 滚动数组优化
- 划分阶段
按照当前背包的载重上限、容量上限进行阶段划分。
- 定义状态
定义状态 dp[w] [v]表示为:将物品装入最多能装重量为 w、容量为 v 的背包中,可以获得的最大价值。
- 状态转移方程
- 初始条件
- 如果背包载重上限为0或者容量上限为0,则无论选取什么物品,可以获得的最大价值一定是0,即:
- dp[w] [0]=0,0≤w≤W
- dp[0] [v]=0,0≤v≤V
- 最终结果
根据我们之前定义的状态, dp[w] [v] 表示为:将物品装入最多能装重量为 w、容量为 v 的背包中,可以获得的最大价值。则最终结果为 dp[W] [V],其中 W 为背包的载重上限,V 为背包的容量上限。
思路 2:代码
1 | class Solution: |
思路 2:复杂度分析
- 时间复杂度:O(n×W×V),其中 n 为物品分组数量,W 为背包的载重上限,V 为背包的容量上限。
- 空间复杂度:O(W×V)。