背包问题概述
背包问题是基于动态规划的一类经典组合优化 NP 完全问题。其问题描述为:给定一组物品,每种物品都有重量和价格,在限定的总重量内,如何选择才能使物品的总价格最高。
根据物品个数分类:
- 01 背包问题:每个物品只有一个
- 完全背包问题:每个物品有无限多个
- 多重背包问题:每件物品有有限个
- 混合背包问题:包含上述三种情况
- 分组背包问题:物品分 n 组,每组最多选一个
根据限定条件个数分类:
- 限定条件只有一个(如体积)
- 限定条件有两个(如体积 + 重量)
根据问法分类:
- 输出方案、求方案总数、最优方案、方案可行性
背包问题种类繁多,但大多从 01 背包演化而来,因此学好 01 背包至关重要。此外,背包问题的优化对时间和空间复杂度提升显著,常见优化方案包括滚动数组、单调队列优化等。
01 背包问题
题目描述
你有一个背包,最多能容纳的体积是 V。现在有 n 个物品,第 i 个物品的体积为 vi,价值为 wi。
- 求这个背包至多能装多大价值的物品?
- 若背包恰好装满,求至多能装多大价值的物品?
输入描述:
第一行两个整数 n 和 V,表示物品个数和背包体积。
接下来 n 行,每行两个数 vi 和 wi,表示第 i 个物品的体积和价值。
其中 1 ≤ n, V, vi, wi ≤ 1000
输出描述: 输出有两行,第一行输出第一问的答案,第二行输出第二问的答案,如果无解请输出 0。
示例 1
输入:3 5
2 10
4 5
1 4
输出:14 9
说明:装第一个和第三个物品时总价值最大,但是装第二个和第三个物品可以使得背包恰好装满且总价值最大。
示例 2
输入:3 8
1 2
6 11
8 6
8 8
输出:8 0
说明:装第三个物品时总价值最大但是不满,装满背包无解。
备注:要求 O(nV) 的时间复杂度,O(V) 空间复杂度。
第一问解题思路
状态表示
定义 dp[i][j] 表示从前 i 个物品中选择,并且物品总体积不超过 j,此时这些选法中能装入背包的最大物品价值。
状态转移方程
对于第 i 个物品,有两种选择:选或不选。
- 不选:
dp[i][j] = dp[i - 1][j] - 选:
dp[i][j] = dp[i - 1][j - v[i]] + w[i](需满足j >= v[i]) 综合:dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - v[i]] + w[i])
初始化
开辟虚拟行列,初始化为 0。dp[0][j] 表示没有物品可放,值为 0;dp[i][0] 表示背包空间为 0,只能为 0。
遍历顺序
从上往下,从左往右遍历。


