codevs 3269 混合背包

混合背包的模板题,数量级较大应当进行优化,比如说读入优化啊,二进制优化啊。

这里说一下二进制优化,假如我们有17件物品,我们可以将其分成1,2,4,8(二的幂次方)+2(剩下的)件

这样实际上只有五件物品我们就可以拼凑出装这些物品的所有状态,然后进行标准的01背包就行了,对于无限多的,

我们可以正序循环或也采用拆分的方法。                                                              ---背包九讲是个好东西

*************************************************************************

#include<cstdio>
#include<algorithm>
#define maxn 300001
using namespace std;
int top=0;
int wei[maxn];
int ver[maxn];
int dp[maxn];
bool note[maxn];
int n,full;
int read()
{
    int now=0;
    int f=1;
    char c=getchar();
    while(c>'9'||c<'0')
    {
        if(c=='-')f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
        now*=10;
        now+=c-'0';
        c=getchar();
    }
    return now*f;
}

int main()
{
    n=read();full=read();
    for(int i=1;i<=n;i++)
    {
        int w=read(),v=read(),num=read();
        if(num==-1)
        {
            top++;
            wei[top]=w;
            ver[top]=v;
            note[top]=true;
            continue;
        }
        int k=1;
        while(num>=k)
        {
                top++;
                wei[top]=w*k;
                ver[top]=v*k;
                num-=k;
                k*=2;        
        }
        if(num)
        {
            top++;
            wei[top]=w*num;
            ver[top]=v*num;
        }
    }
    for(int i=1;i<=top;i++)
    {
        if(note[i])
        {
            for(int j=wei[i];j<=full;j++)
            {
                dp[j]=max(dp[j],dp[j-wei[i]]+ver[i]);
            }    
        }
        else
        for(int j=full;j>=wei[i];j--)
        {
            dp[j]=max(dp[j],dp[j-wei[i]]+ver[i]);
        }
    }
    printf("%d",dp[full]);
    return 0;
}
原文地址:https://www.cnblogs.com/luoyibujue/p/6890087.html