完全背包问题

有 n 种重量和价值分别为 wi 和 vi 的物品 , 从这些物品中挑选总重量不超过 W 的物品,使得挑选出的物品的总价值最大。

和0-1 背包相比,完全背包对于每一件物品可以挑选任意多件。

转移方程: 

                                          

完全背包_完全背包

                                                     

完全背包_状态转移_02

void solve() {
for(int i = 0 ; i<n ; i++ ) {
for(int j = 0 ; j<=W; j++) {
for(int k = 0 ; k*w[i] <=j ; k++ ) {
dp[i+1][j] = max(dp[i+1][j] , dp[i][j-k*w[i]] + k*v[i]) ;
}
}
}
cout<< dp[n][W] ;
}

完全背包_i++_03

     我们看它的状态转移,对于 dp[3][3] 它是由 dp[2][1] 和 dp[2][3] 转移的 , 对于 dp[3][5] , 它是由 dp[2][1] 和 dp[2][3]

我们发现,可以简化为dp[3][5]是由 dp[3]3] 和 dp[2][5] 转移的,对于 dp[3][7] 是由 dp[3][5] 和dp[2][7] 转移的,这时, 每个状态都是由两个状态转移的。

完全背包_完全背包_04

上图就是简化后的,

void solve1() {

for(int i = 0 ; i<n ; i++ ) {
for(int j = 0 ; j<=W; j++) {
if(j<w[i]){
dp[i+1][j] = dp[i][j] ;
}else {
dp[i+1][j] = max(dp[i][j] , dp[i+1][j-w[i]] + v[i]) ;
}

}
}
cout<< dp[n][W] ;

}

这时的转移方程变成 : 

                                          

完全背包_状态转移_05

空间优化 :

void solve3() {

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] ) ;
}
}

}