HDU2844【背包问题(二进制优化)】

题意:
n,m
给出A1,A2,A3...AN;C1,C2,C3...CN;
给出硬币的价值和个数,问在1-M中间能构造出多少个组合
思路:
n种物品的价值,n种物品的个数;

一种物品能组成多种物品的0/1背包

#include<bits/stdc++.h>
using namespace std;

const int N=1e2+10;
const int M=100000+10;

int n,m;
int val[N],num[N];
bool dp[M];

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

void Complete(int v)
{
    for(int i=v;i<=m;i++)
        if(dp[i-v])
            dp[i]=true;
}

int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        if(!n&&!m) break;
        for(int i=1;i<=n;i++)
            scanf("%d",&val[i]);
        for(int i=1;i<=n;i++)
            scanf("%d",&num[i]);
        int k,v;
        dp[0]=true;
        for(int i=1;i<=m;i++)
            dp[i]=false;
        for(int i=1;i<=n;i++)
        {
            if(num[i]*val[i]>=m)
                Complete(val[i]);
            else
            {
                k=1;
                while(k<=num[i])
                {
                    v=val[i]*k;
                    Oneorzero(v);
                    num[i]-=k;
                    k<<=1;
                }
                v=val[i]*num[i];
                Oneorzero(v);
            }
        }
        int ans=0;
        for(int i=1;i<=m;i++)
            if(dp[i])
                ans++;
        printf("%d
",ans);
    }
    return 0;
}



原文地址:https://www.cnblogs.com/keyboarder-zsq/p/6777453.html