背包问题
0/1 背包问题
给定 N 件物品,每件物品有 重量 w[i] 和 价值 v[i],现有一个容量为 W 的背包,求能装入的最大总价值。
思路
-
定义状态
dp[i][j]表示前i件物品,在容量j的背包下的最大价值。
-
状态转移方程
- 不选第 i 件物品:
dp[i][j] = dp[i-1][j] - 选第 i 件物品(前提是能放得下):
dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]] + v[i])
- 不选第 i 件物品:
-
初始化
dp[0][j] = 0(背包容量为j,但没有物品)dp[i][0] = 0(有物品,但背包容量为0)
-
优化
- 使用 滚动数组 降低空间复杂度,从
dp[i][j]改为dp[j],逆序遍历j以保证状态不被覆盖。 -
![]()
-
0/1 背包问题的递归解法(C#)
递归方法是一种 自顶向下(Top-Down) 的方式来解决 0/1 背包问题,适合理解 子问题拆解 的思想。但由于存在大量重复计算,需要使用 记忆化搜索(Memoization) 来优化效率。
递归思路
-
定义递归函数:
KnapsackRecursive(n, capacity)表示前n个物品在总容量capacity下的最大价值。
-
状态转移方程:
- 如果不选当前物品:
KnapsackRecursive(n - 1, capacity) - 如果选当前物品(前提是容量足够): KnapsackRecursive(n−1,capacity−weights[n−1])+values[n−1]KnapsackRecursive(n - 1, capacity - weights[n-1]) + values[n-1]KnapsackRecursive(n−1,capacity−weights[n−1])+values[n−1]
- 取两者的最大值: dp[n,capacity]=max(KnapsackRecursive(n−1,capacity),KnapsackRecursive(n−1,capacity−weights[n−1])+values[n−1])dp[n, capacity] = \max(KnapsackRecursive(n - 1, capacity), KnapsackRecursive(n - 1, capacity - weights[n-1]) + values[n-1])dp[n,capacity]=max(KnapsackRecursive(n−1,capacity),KnapsackRecursive(n−1,capacity−weights[n−1])+values[n−1])
- 如果不选当前物品:
-
终止条件:
- 当
n == 0或capacity == 0时,返回0(没有物品或容量为 0)。
- 当
-
优化:记忆化搜索
- 使用
memo[n, capacity]记录已经计算过的结果,避免重复计算,提高效率。
- 使用
-
-
![]()
-
- 使用 滚动数组 降低空间复杂度,从



浙公网安备 33010602011771号