N个物品,每个物品有一个wi的重量和pi的价值,现在有一个重W的背包问放进物品后的最大值。
//首先是记忆化搜索
//dp[i][j] 在前i件物品里面选择不超过重量j的最大价值
int rec(int i, int j)
{
if(dp[i][j] >= 0) //在此之前需要memset(dp, -1, sizeof(dp))
return dp[i][j];
int res;
if(i == n)
res = 0; //没有物品选择了
else if(j < w[i]) //当前重量无法装下第i件物品
res = rec(i + 1, j);
else
res = max(rec(i + 1, j), rec(i + 1, j - w[i]) + p[i]);
return res = dp[i][j];
}
基于上面的思想我们有递推式
dp[i][j]={max(dp[i−1][j],dp[i−1][j−w[i]]+p[i])dp[i−1][j](j >=w[i] )(j < w[i])
根据递推式有
int ZeroOnePack()
{
memset(dp, 0, sizeof(dp));
for(int i = 0; i < n; ++i)
for(int j = 0; j <= W; ++j)
dp[i + 1][j] = j >= w[i]? max(dp[i][j], dp[i][j - w[i]] + p[i]) : dp[i][j];
return dp[n][W];
}
这样的话时间复杂度和空间复杂度都是O(nW) 可以对空间复杂度进行优化有
dp[j]=max(dp[j],dp[j−w[i]]+p[i])
每一次获取dp[j] 都必须要只知道 前一次的 dp[j] 和 dp[j-w[i]]
for(int i = 0; i < n; ++i)
for(int j = W; j >= w[i]; --j)
dp[j] = max(dp[j], dp[j-w[i]]);