HDU 2844 多重背包模板

给出n个数和m

每个数给出出现次数和价值,问任意组合组成不大于M的价值,共能产生多少个数

多重背包的的二进制优化写法  模板mark一下

二进制优化原理:

1、2、4可以组合出所有小于8的数;
1、2、4、8可以组合出所有小于16的数;
1、2、4、8、16可以组合出所有小于32的数;
 ……



#include "stdio.h"
#include "string.h"

int n,m;
int dp[100010];
void complete_pack(int v)
{
    int i;
    for (i=v;i<=m;i++)
        if (dp[i-v]==1) dp[i]=1;
}

void onezero_pack(int v)
{
    int i;
    for (i=m;i>=v;i--)
        if (dp[i-v]==1) dp[i]=1;
}

void multiple_pack(int v,int c)
{
    int k;
    if (v*c>=m)
        complete_pack(v);
    else
    {
        k=1;
        while (k<c)
        {
            onezero_pack(k*v);
            c-=k;
            k*=2;
        }
        onezero_pack(c*v);
    }
}
int main()
{
    int v[101],c[101];
    int i,ans;
    while (scanf("%d%d",&n,&m)!=EOF)
    {
        if (n+m==0) break;
        for (i=1;i<=n;i++)
            scanf("%d",&v[i]);
        for (i=1;i<=n;i++)
            scanf("%d",&c[i]);

        memset(dp,0,sizeof(dp));
        dp[0]=1;
        for (i=1;i<=n;i++)
            multiple_pack(v[i],c[i]);
        ans=0;
        for (i=1;i<=m;i++)
            if (dp[i]!=0) ans++;
        printf("%d\n",ans);
    }
    return 0;

}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值