完全背包
之前我讲过0-1背包,这里讲解完全背包。
一. 问题描述
假设我们给定n个物品,每个物品具有重量weight以及价值value,第i个物品的重量为weight[i], 价值为value[i]。同时给定一个容量为m的背包,求解背包里装入的物品价值之和的最大值。
不同于0-1背包问题(每件物品最多放入一次),多重背包可以放入每件物品无数次,只要满足背包的容量限制。
二. 分析
利用跟0-1背包相同的分析思路,我们考虑第i件物品:放入或者不放。如果不放,那么dp[i][j]=dp[i-1][j]; 如果放入,那么dp[i][j]=dp[i][j-weight[i]]+value[i]. 这里是跟0-1背包不同之处。这一次我们放入了i,之前的则是
dp[i][j-weight[i]]
我们用了前i种物品,至于放没放入物品i我们不知道,有可能没放,也可能放了很多次。整合起来,状态转移方程是
dp[i][j]=max{dp[i-1][j], dp[i][j-weight[i]]+value[i]}.
示意图如下:
优化存储空间,我们可以得到新的状态转移方程
dp[j]=max{dp[j], dp[j-weight[i]]+value[i]}.
可以看到这个方程与0-1背包的完全相同,但是意义是不一样的!反应在代码上
memset(dp,0,sizeof(dp)); for(i=0; i<n; i++) for(j=weight[i]; j<=m; j++) dp[j]=max(dp[j],dp[j-weight[i]]+value[i]);
差别在于j是升序。参考上图很容易理解,与0-1背包的分析是同样的思路,这里不再赘述。
参考了以下博文: