背包问题(Knapsack Problem)是组合优化中的经典问题,核心目标是在有限容量的背包中选择物品,使总价值最大化,同时不超过重量限制。根据物品是否可分割,主要分为以下三类:
一、0-1背包问题(0-1 Knapsack Problem)
特点:每个物品只能选或不选(0或1),不可分割。
数学模型:
- 物品集合:( n ) 个物品,每个物品 ( i ) 有重量 ( w_i ) 和价值 ( v_i )。
- 背包容量:( W )。
- 目标:最大化总价值 ( \sum_{i=1}^n v_i x_i ),满足 ( \sum_{i=1}^n w_i x_i \leq W ),其中 ( x_i \in {0,1} )。
解法
-
动态规划(DP)
- 状态定义:( dp[i][j] ) 表示前 ( i ) 个物品中选,容量为 ( j ) 时的最大价值。
- 转移方程:
[
dp[i][j] = \begin{cases}
dp[i-1][j] & \text{(不选第 } i \text{ 个物品)} \
\max(dp[i-1][j], dp[i-1][j-w_i] + v_i) & \text{(选第 } i \text{ 个物品,需 } j \geq w_i \text{)}
\end{cases}
] - 优化空间:可压缩为一维数组 ( dp[j] ),逆序更新(避免重复选同一物品)。
-
回溯法(暴力枚举)
- 递归遍历所有可能的选法,剪枝排除超过容量的情况。适用于 ( n ) 较小的场景(如 ( n \leq 20 ))。
-
分支限界法
- 通过优先队列(如最大价值优先)搜索可行解,利用上界剪枝提高效率。
二、完全背包问题(Unbounded Knapsack Problem)
特点:每个物品可无限选取(数量不限)。
数学模型:与0-1背包类似,但 ( x_i ) 为非负整数(可重复选)。
解法
-
动态规划
- 状态定义:同0-1背包,但转移方程允许重复选同一物品。
- 转移方程:
[
dp[i][j] = \max(dp[i-1][j], dp[i][j-w_i] + v_i) \quad \text{(选第 } i \text{ 个物品多次,需 } j \geq w_i \text{)}
] - 优化空间:一维数组 ( dp[j] ),顺序更新(允许重复选当前物品)。
-
数学优化
- 对于每个物品,计算单位重量价值 ( v_i/w_i ),优先选性价比高的物品(但需注意可能无法整除容量,需结合余数调整)。
三、多重背包问题(Bounded Knapsack Problem)
特点:每个物品有固定数量限制 ( c_i ),即最多选 ( c_i ) 个。
数学模型:( x_i \leq c_i ),其余同完全背包。
解法
-
动态规划(直接法)
- 状态定义:同前,转移方程需枚举选 ( k ) 个物品 ( i )(( 0 \leq k \leq c_i )),但时间复杂度较高(( O(nW\sum c_i) ))。
-
二进制优化
- 将每个物品拆分为 ( \log_2 c_i ) 个“新物品”(如数量 ( c_i = 5 ) 拆分为 ( 1, 2, 2 )),转化为0-1背包问题,降低时间复杂度至 ( O(nW \log c_i) )。
-
单调队列优化
- 通过滑动窗口优化转移过程,时间复杂度 ( O(nW) ),适用于大数据量。
四、背包问题的扩展与变种
-
二维背包问题
- 增加另一个限制条件(如体积、价格等),状态变为 ( dp[i][j][k] ),复杂度更高。
-
分组背包问题
- 物品分为若干组,每组中只能选一个物品,求最大价值。
-
背包问题的变形
- 硬币问题:求凑出目标金额的最少/最多硬币数(完全背包变种)。
- 子集和问题:判断是否存在子集和为目标值(0-1背包的可行性问题)。
五、背包问题的应用场景
- 资源分配:如预算分配、任务调度(有限资源下最大化收益)。
- 组合优化:物流配送(车辆载重限制下最大化货物价值)。
- 算法基础:作为动态规划的经典案例,用于理解状态转移和优化思想。
总结
类型 | 物品是否可分割 | 解法核心 | 时间复杂度 |
---|---|---|---|
0-1背包 | 不可分割 | 动态规划(一维优化)、回溯 | ( O(nW) ) |
完全背包 | 可无限分割 | 动态规划(顺序更新) | ( O(nW) ) |
多重背包 | 数量有限 | 二进制拆分、单调队列优化 | ( O(nW \log c) ) |
背包问题的解法需根据具体限制条件选择,动态规划是最常用的通用方法,而优化技巧(如空间压缩、二进制拆分)可显著提升效率。
背包问题(Knapsack Problem)是组合优化中的经典问题,核心目标是在有限容量的背包中选择物品,使总价值最大化,同时不超过重量限制。根据物品是否可分割,主要分为以下三类:
一、0-1背包问题(0-1 Knapsack Problem)
特点:每个物品只能选或不选(0或1),不可分割。
数学模型:
- 物品集合:( n ) 个物品,每个物品 ( i ) 有重量 ( w_i ) 和价值 ( v_i )。
- 背包容量:( W )。
- 目标:最大化总价值 ( \sum_{i=1}^n v_i x_i ),满足 ( \sum_{i=1}^n w_i x_i \leq W ),其中 ( x_i \in {0,1} )。
解法
-
动态规划(DP)
- 状态定义:( dp[i][j] ) 表示前 ( i ) 个物品中选,容量为 ( j ) 时的最大价值。
- 转移方程:
[
dp[i][j] = \begin{cases}
dp[i-1][j] & \text{(不选第 } i \text{ 个物品)} \
\max(dp[i-1][j], dp[i-1][j-w_i] + v_i) & \text{(选第 } i \text{ 个物品,需 } j \geq w_i \text{)}
\end{cases}
] - 优化空间:可压缩为一维数组 ( dp[j] ),逆序更新(避免重复选同一物品)。
-
回溯法(暴力枚举)
- 递归遍历所有可能的选法,剪枝排除超过容量的情况。适用于 ( n ) 较小的场景(如 ( n \leq 20 ))。
-
分支限界法
- 通过优先队列(如最大价值优先)搜索可行解,利用上界剪枝提高效率。
二、完全背包问题(Unbounded Knapsack Problem)
特点:每个物品可无限选取(数量不限)。
数学模型:与0-1背包类似,但 ( x_i ) 为非负整数(可重复选)。
解法
-
动态规划
- 状态定义:同0-1背包,但转移方程允许重复选同一物品。
- 转移方程:
[
dp[i][j] = \max(dp[i-1][j], dp[i][j-w_i] + v_i) \quad \text{(选第 } i \text{ 个物品多次,需 } j \geq w_i \text{)}
] - 优化空间:一维数组 ( dp[j] ),顺序更新(允许重复选当前物品)。
-
数学优化
- 对于每个物品,计算单位重量价值 ( v_i/w_i ),优先选性价比高的物品(但需注意可能无法整除容量,需结合余数调整)。
三、多重背包问题(Bounded Knapsack Problem)
特点:每个物品有固定数量限制 ( c_i ),即最多选 ( c_i ) 个。
数学模型:( x_i \leq c_i ),其余同完全背包。
解法
-
动态规划(直接法)
- 状态定义:同前,转移方程需枚举选 ( k ) 个物品 ( i )(( 0 \leq k \leq c_i )),但时间复杂度较高(( O(nW\sum c_i) ))。
-
二进制优化
- 将每个物品拆分为 ( \log_2 c_i ) 个“新物品”(如数量 ( c_i = 5 ) 拆分为 ( 1, 2, 2 )),转化为0-1背包问题,降低时间复杂度至 ( O(nW \log c_i) )。
-
单调队列优化
- 通过滑动窗口优化转移过程,时间复杂度 ( O(nW) ),适用于大数据量。
四、背包问题的扩展与变种
-
二维背包问题
- 增加另一个限制条件(如体积、价格等),状态变为 ( dp[i][j][k] ),复杂度更高。
-
分组背包问题
- 物品分为若干组,每组中只能选一个物品,求最大价值。
-
背包问题的变形
- 硬币问题:求凑出目标金额的最少/最多硬币数(完全背包变种)。
- 子集和问题:判断是否存在子集和为目标值(0-1背包的可行性问题)。
五、背包问题的应用场景
- 资源分配:如预算分配、任务调度(有限资源下最大化收益)。
- 组合优化:物流配送(车辆载重限制下最大化货物价值)。
- 算法基础:作为动态规划的经典案例,用于理解状态转移和优化思想。
总结
类型 | 物品是否可分割 | 解法核心 | 时间复杂度 |
---|---|---|---|
0-1背包 | 不可分割 | 动态规划(一维优化)、回溯 | ( O(nW) ) |
完全背包 | 可无限分割 | 动态规划(顺序更新) | ( O(nW) ) |
多重背包 | 数量有限 | 二进制拆分、单调队列优化 | ( O(nW \log c) ) |
背包问题的解法需根据具体限制条件选择,动态规划是最常用的通用方法,而优化技巧(如空间压缩、二进制拆分)可显著提升效率。