luogu P1776 宝物筛选_NOI导刊2010提高(02) | 多重背包(二进制拆分)

有许多种物品,每种物品有多个,个数已知,求最大价值

luogu P1776 宝物筛选_NOI导刊2010提高(02)

假设物品 a 有 34 个

那么将34拆分为1,2,4,8,16,3总共6个数

这6个数可以任意组合表示从1到34所有的数

那么就将1个a物品,2个a物品,4个a物品......各自看成一个整体,它们各自的取与不取可以表示从取1 个a物品到取34个a物品的所有可能

拆分之后即为01背包问题

#include<cstdio>
using namespace std;
int n,maxw,v[100010],w[100010],m[100010],vi,wi,mi,x,ans[100010];
int main()
{
    scanf("%d%d",&n,&maxw);
    int k=0;
    for(int i=1;i<=n;i++)
    {
        x=1;
        scanf("%d%d%d",&vi,&wi,&mi);
        while(x<=mi)
        {
            mi-=x;
            k++;
            v[k]=vi*x;
            w[k]=wi*x;
            m[k]=mi*x;
            x*=2;
            //printf("k=%d,v=%d,w=%d,m=%d
",k,v[k],w[k],m[k]);
        }
        if(mi)
        {
        k++;
        v[k]=vi*mi;
        w[k]=wi*mi;
        m[k]=mi*mi;
        //printf("k=%d,v=%d,w=%d,m=%d
",k,v[k],w[k],m[k]);
        }
    }
    for(int i=1;i<=k;i++)
    {
        for(int j=maxw;j>=w[i];j--)
        {
            if(ans[j]<ans[j-w[i]]+v[i]) ans[j]=ans[j-w[i]]+v[i];
        }
    }
    printf("%d",ans[maxw]);
    return 0;
}
原文地址:https://www.cnblogs.com/QAQq/p/10300939.html