01背包问题详解

来源:互联网 发布:少儿编程培训班费用 编辑:程序博客网 时间:2024/05/21 10:59

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[i1][j],dp[i1][jw[i]]+p[i])dp[i1][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[jw[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]]);
0 0