文章目录
一维DP数组的解法
背包最大重量为4。
物品重量和价值为:
问背包能背的物品最大价值是多少?
在我们使用二维DP数组的时候,递推公式是dp[i][j]=max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i])
.
如果要降为一维DP数组,就是用dp[j]
来表示递推。这里用j是为了j的含义和二维DP数组保持一致,下标含义都是背包的容量。
二维DP递推思路
原始的二维DP状态转移方程是:dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i])
。
这个方程意味着,对于第i个物品和当前背包容量j,我们要么选择放入这个物品,要么不放。如果放入这个物品,就需要看在容量为j-weight[i]
时,放入前i-1个物品的最大价值(也就是dp[i - 1][j - weight[i]] + value[i]
),如果不放入这个物品,就是dp[i - 1][j]
。然后取这两者之间的最大值。
二维背包DP数组情况示例如下图所示。
我们其实可以发现,如果把dp[i - 1]
那一层拷贝到dp[i]
上,表达式完全可以是:dp[i][j] = max(dp[i][j], dp[i][j - weight[i]] + value[i]);
,与其把dp[i - 1]这一层拷贝到dp[i]上,不如只用一个一维数组了,只用dp[j](一维数组,也可以理解是一个滚动数组)。
滚动数组优化思路(重要)
leetcode题目343.整数拆分 里,其实有类似滚动数组的思想。整数拆分题目代码:
class Solution {
public:
int integerBreak(int n) {
//DP数组建立,注意数组本身容量赋值
vector<int>dp(n+1,0);
//初始化
dp[2]=1;
for(int i=3;i<=n;i++){
for(int j=1;j<=i-1;j++){
dp[i]=max(dp[i],max(j*(i-j),j*dp[i-j])