完全背包问题


背包九讲中解释的非常清楚了,这里不多说。

    第一种思路:把第i种物品拆成费用为c[i]*2^k、价值为w[i]*2^k的若干件物品,其中k满足 c[i]*2^k<=V。这是二进制的思想,因为不管最优策略选几件第i种物品,总可以表示成若干个2^k件物品的和。这样把每种物品拆成O(log V/c[i])件物品,是一个很大的改进。这样就可以把问题转化为01背包了,然后就可以采用01背包的各种求法了:)
  1. void Divide(int *n, int *v)//将一件物品拆分
  2. {
  3.     int i, k, t;
  4.     t=*n;
  5.     for (i=1; i<=t; i++){
  6.         for (k=1; cost[i]*pow(2.0, k)<=*v; k++){
  7.             cost[++(*n)]=cost[i]*(int)pow(2.0, k);
  8.             weight[(*n)]=weight[i]*(int)pow(2.0, k);
  9.         }
  10.     }
  11. }
第二种思路,将01背包中一维数组解决方案的第二个循环次序倒过来,看伪码:
for i=1....N
     for j=0....V
          f[j]=max(f[v-cost[i]+weight[i], f[j])
至于为什么参见背包九讲。
  1. int Cbag2(int n, int v)//运用循环颠倒的方法解决完全背包
  2. {
  3.     int i, j, sum=0, bound;
  4.     for (i=0; i<=v; i++){//初始化  
  5.         f2[i]=0;
  6.     }
  7.     for (i=1; i<=n; i++){
  8.         for (j=cost[i]; j<=v; j++){
  9.             f2[j]=max(f2[j-cost[i]]+weight[i], f2[j]);
  10.         }
  11.     }
  12.     return f2[v];
  13. }

          

你可能感兴趣的:(c)