完全背包问题


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

    第一种思路:把第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. }

          
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值