1 #include<bits/stdc++.h> 2 using namespace std; 3 4 5 /*初始化的细节问题 我们看到的求最优解的背包问题题目中,事实上有两种不太相同的问法。 6 7 8 有的题目要求“恰好装满背包”时的最优解,有的题目则并没有要求必须把背包装满。一种区别这两种问法的实现方法是在初始化的时候有所不同。 9 如果是第一种问法,要求恰好装满背包,那么在初始化时除了 f[0]为 0 其它 f[1..V]均设为-∞,这样就可以保证最终得到的 f[N]是一种恰好装满背包 10 的最优解。 11 如果并没有要求必须把背包装满,而是只希望价格尽量大,初始化时应该将 f[0..V]全部设为 0。 12 13 14 为什么呢?可以这样理解:初始化的 f 数组事实上就是在没有任何物品可以放入 背包时的合法状态。 15 如果要求背包恰好装满,那么此时只有容量为 0 的背包可能 被价值为 0 的 nothing“恰好装满”,其它容 16 量的背包均没有合法的解,属于未 定义的状态,它们的值就都应该是-∞了。如果背包并非必须被装满,那 17 么任何 容量的背包都有一个合法解“什么都不装”,这个解的价值为 0,所以初始时状 态的值也就全部为 0 了。*/ 18 19 20 21 //01背包 22 void ZeroOnePack(cost,weight) 23 { 24 for(int v=V;v>=cost;v--) 25 f[v]=max(f[v],f[v-cost]+weight); 26 } 27 28 for i=1...N 29 ZeroOnePack(c[i],w[i]); 30 31 32 //完全背包 33 void CompletePack(cost,weight) 34 { 35 for(int v=cost;v<=V;v++) 36 f[v]=max(f[v],f[v-cost]+weight); 37 38 } 39 40 for i=1...N 41 CompletePack(c[i],w[i]); 42 43 44 //多重背包 45 46 //方法一:每种物品分解为多个 01背包求解 47 void MultiplePack(cost,weight,amount) 48 { 49 for(int v=V;v>=cost;v--) 50 for(int k=0;k<amount;k++) 51 f[v]=max(f[v],f[v-cost]+weight); 52 } 53 54 for i=1...N 55 MultiplePack(c[i],w[i],n[i]); 56 57 58 //方法二:二进制优化 59 void MultiplePack(cost,weigt,amount) 60 { 61 if(cost*amount>=V)//全部装不下 当完全背包 可取任意多个 62 { 63 CompletePack(cost,weight); 64 return ; 65 } 66 67 int k=1; 68 while(k<amount) 69 { 70 ZeroOnePack(k*cost,k*weight); 71 amount-=k; 72 k<<1;//k*=2; 73 } 74 ZeroOnePack(amount*cost,amount*weight); 75 }