0-1 背包问题
动态规划解决 0-1 背包问题
问题
有 N 件物品和一个容量是 V 的背包,每件物品只有一件。第 i 件物品的体积是 v[i],价值是 w[i]。求解将哪些物品装入背包,可使总体积不超过背包容量,且总价值最大。
示例 1:
输入: N = 3, V = 4, v = [4,2,3], w = [4,2,3]
输出: 4
解释: 只选第一件物品,可使价值最大。
示例 2:
输入: N = 3, V = 5, v = [4,2,3], w = [4,2,3]
输出: 5
解释: 不选第一件物品,选择第二件和第三件物品,可使价值最大。
解答
动态规划(二维数组)
function knapsack(N, V, v, w) {
// dp[i][j] 表示前 i 件物品,背包容量为 j 时的最大价值
const dp = Array.from({ length: N + 1 }, () => Array(V + 1).fill(0));
for (let i = 1; i <= N; i++) {
for (let j = 0; j <= V; j++) {
// 不选第 i 件物品
dp[i][j] = dp[i - 1][j];
// 如果能选第 i 件物品,取最大值
if (j >= v[i - 1]) {
dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - v[i - 1]] + w[i - 1]);
}
}
}
return dp[N][V];
}
动态规划(一维数组优化)
function knapsack(N, V, v, w) {
const dp = Array(V + 1).fill(0);
for (let i = 0; i < N; i++) {
// 从后向前遍历,避免重复使用同一物品
for (let j = V; j >= v[i]; j--) {
dp[j] = Math.max(dp[j], dp[j - v[i]] + w[i]);
}
}
return dp[V];
}
关键点
- 状态定义:
dp[i][j]表示前 i 件物品在容量 j 下的最大价值 - 状态转移:对每件物品选择”选”或”不选”,取最大值
- 空间优化:使用一维数组时必须从后向前遍历,防止物品被重复选择
- 时间复杂度 O(N×V),空间复杂度可优化至 O(V)
目录