背包模板(01、完全、多重)

这是一个多重背包的模板,也是十分好用的一种模板,因为这个比直接拆除01 背包来做

要省些时间。这是为啥呢,首先先由我讲一下为什么能换成01 背包吧。

 

 

举个例子。假如给了我们 价值为 2,但是数量却是10 的物品,我们应该把10给拆开,要知道二进制可是能够表示任何数的,所以10 就是可以有1,2, 4,8之内的数把它组成,一开始我们选上 1了,然后让10-1=9,再选上2,9-2=7,在选上 4,7-4=3,

而这时的3<8了,所以我们就是可以得出 10由 1,2,4,3,来组成,就是这个数量为1,2,3,4的物品了,那么他们的价值是什么呢,是2,4,6,8,也就说给我们的价值为2,数量是10的这批货物,已经转化成了价值分别是2,4,6,8元的货物了,每种只有一件哎!!!!这就是二进制优化的思想。

 

 

那为什么会有完全背包和01 背包的不同使用加判断呢?原因也很简单啊,当数据很大,大于背包的容纳量时,我们就是在这个物品中取上几件就是了,取得量时不知道的,也就理解为无限的啦,这就是完全背包啦,反而小于容纳量的就是转化为01背包来处理就是了,可以大量的省时间。

#include<stdio.h>    
#include<string.h>    
#include<stdlib.h>    
#define N 1000         //物品个数     
#define M 100000000    //所有物品可能的最大价值     
int m[N],c[N],w[N],f[M];    
int V;    
int max(int a,int b){return a>b?a:b;}    
void ZeroOnePack(int cost,int weight)    
{    
    int v;    
    for(v=V;v>=cost;v--) f[v]=max(f[v],f[v-cost]+weight);    
}    
void CompletePack(int cost,int weight)    
{    
    int v;    
    for(v=cost;v<=V;v++)    
        f[v]=max(f[v],f[v-cost]+weight);    
}    
void MultiplePack(int cost,int weight,int amount)    
{    
    int k;    
    if(cost*amount>=V)    
    {    
        CompletePack(cost,weight);    
        return;    
    }    
    k=1;    
    while(k<amount)    //二进制优化
    {    
        ZeroOnePack(k*cost,k*weight);    
        amount=amount-k;    
        k=k*2;    
    }    
    ZeroOnePack(amount*cost,amount*weight);    
}    
int main()    
{    
    int n,i;    
    scanf("%d %d",&n,&V);    
                                                   // 两种不同的初始化方式,根据情况自行选择     
    //memset(f,0,sizeof(f[0])*(V+1));              // 只希望价格尽量大     
    //memset(f,-M,sizeof(f[0])*(V+1));f[0]=0;      // 要求恰好装满背包     
    for(i=0;i<n;i++) scanf("%d %d %d",m+i,c+i,w+i);    
    for(i=0;i<n;i++) MultiplePack(c[i],w[i],m[i]);    
    printf("%d\n",f[V]);    
    system("PAUSE");    
    return 0;    
}    

猜你喜欢

转载自blog.csdn.net/dilly__dally/article/details/80374951