完全背包问题

Posted pandapig

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了完全背包问题相关的知识,希望对你有一定的参考价值。

完全背包问题

递推关系:

dp[0][j]=0

dp[i+1][j]=max{dp[i][j-k*w[i]]+k*v[i]|0<=k}

但直接这样去写程序是三重循环,时间复杂度为O(mW^2).

在这个算法中有多余的计算:

dp[i+1][j]的计算中选择k(k>=1) i 物品的情况,与在dp[i+1][j-w[i]]的计算中选择k-1的情况是相同的,所以dp[i+1][j]的递推中k>=1部分的计算已经在dp[i+1][j-w[i]]的计算中完成了。那么可以按照如下方式进行变形:

dp[i+1][j]

=max{dp[i][j-k*w[i]]+k*v[i]|0<=k}

=max(dp[i][j],max{dp[i][j-k*w[i]]+k*v[i]|1<=k})

=max(dp[i][j],max{dp[i][(j-w[i])-k*w[i]]+k*v[i]|0<=k}+v[i])

=max(dp[i][j],dp[i+1][j-w[i]]+v[i])

这样一来就可以用O(nW)时间解决问题

?

void solve(){

for(int i = 0; i < n; i++){

for(int j = ;j <= W;j++){

if(j<W[i]){

????dp[i+1][j] = dp[i][j];

}else {

????dp[i+1][j] = dp[i+1][ j-w[i] ] + v[i] );

}
}

}

printf("%d ", dp[n][W]);

?

使用了滚动数组,并且只是01背包代码的修改而已

回想一下我们学01背包滚动数组版本的时候,是不是要求数组第二维的j一定要从后往前,从大到小来遍历,就是为了防止新数据被新数据覆盖

我们只允许旧数据被新数据覆盖(拿一次还是不拿),那么新数据被新数据覆盖在实际层面怎么理解呢,就是(拿j次还是拿j-1次)

所以接下来我们在01背包代码的基础上让第二维的j从小到大,从前往后

如果说新数据覆盖新数据更好,那么我就给你覆盖,也就是如果已经拿了几个这种物品了,如果再拿几个会更好,那我就给你拿

01背包问题的情况

?

int dp[MAX_W+1];

?

void solve(){

????for(int i = 0; i < n; i++){

????for(int j = W; j >= w[i]; j--){

????dp[j] = max(dp[j], dp[ j – w[i]] + v[i]);

}

}

printf("%d ", dp[W]);

}

?

01背包问题的情况

?

int dp[MAX_W+1];

?

void solve(){

????for(int i = 0; i < n; i++){

????for(int j = w[i]; j <= W; j++){

????dp[j] = max(dp[j], dp[ j – w[i]] + v[i]);

}

}

printf("%d ", dp[W]);

}

以上是关于完全背包问题的主要内容,如果未能解决你的问题,请参考以下文章

背包问题:0-1背包完全背包和多重背包

01背包和完全背包问题

01背包完全背包多重背包分组背包总结

动态规划——背包问题python实现(01背包完全背包多重背包)

动态规划之背包问题-01背包+完全背包+多重背包

背包问题(01背包,完全背包,多重背包)