码迷,mamicode.com
首页 > 其他好文 > 详细

完全背包问题

时间:2020-07-25 23:28:08      阅读:69      评论:0      收藏:0      [点我收藏+]

标签:循环   printf   直接   计算   01背包   white   font   解决   选择   

完全背包问题

递推关系:

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\n", 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\n", 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\n", dp[W]);

}

完全背包问题

标签:循环   printf   直接   计算   01背包   white   font   解决   选择   

原文地址:https://www.cnblogs.com/Pandapig/p/13375641.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!