背包九讲中解释的非常清楚了,这里不多说。
第一种思路:把第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背包的各种求法了:)
- void Divide(int *n, int *v)//将一件物品拆分
- {
- int i, k, t;
- t=*n;
- for (i=1; i<=t; i++){
- for (k=1; cost[i]*pow(2.0, k)<=*v; k++){
- cost[++(*n)]=cost[i]*(int)pow(2.0, k);
- weight[(*n)]=weight[i]*(int)pow(2.0, k);
- }
- }
- }
for i=1....N
for j=0....V
f[j]=max(f[v-cost[i]+weight[i], f[j])
至于为什么参见背包九讲。
- int Cbag2(int n, int v)//运用循环颠倒的方法解决完全背包
- {
- int i, j, sum=0, bound;
- for (i=0; i<=v; i++){//初始化
- f2[i]=0;
- }
- for (i=1; i<=n; i++){
- for (j=cost[i]; j<=v; j++){
- f2[j]=max(f2[j-cost[i]]+weight[i], f2[j]);
- }
- }
- return f2[v];
- }