HDU-2844-Coins

来源:互联网 发布:夏季太极服淘宝网 编辑:程序博客网 时间:2024/06/05 17:38

这个题是一个多重背包问题,只不过要求你求出能够组合出不同数的个数,其实仔细看可以发现dp[i]==i满足这个条件的时候就应该找到对应的一个满足一个组合的数

所以在多重背包计算完成以后只需要遍历一次,统计出dp[i]==i的个数即为答案

代码:

#include<cstdio>#include<cstring>#include<iostream>using namespace std;const int maxn=101;int n,m,ans,num[maxn],c[maxn],dp[100010];void CompletePack(int cost,int weight){    for(int i=cost;i<=m;i++)dp[i]=max(dp[i],dp[i-cost]+weight);}void ZeroOnePack(int cost,int weight){    for(int i=m;i>=cost;i--)dp[i]=max(dp[i],dp[i-cost]+weight);}void MultiplyPack(int cost,int weight,int amount){    if(cost*amount>=m)CompletePack(cost,weight);    else    {int k=1;while(k<amount){    ZeroOnePack(k*cost,k*weight);    amount-=k;    k<<=1;}ZeroOnePack(amount*cost,amount*weight);    }}int main(){    while(scanf("%d%d",&n,&m)&&(n+m))    {ans=0;memset(dp,0,sizeof(dp));for(int i=0;i<n;i++)    scanf("%d",&c[i]);for(int i=0;i<n;i++)    scanf("%d",&num[i]);for(int i=0;i<n;i++)    MultiplyPack(c[i],c[i],num[i]);for(int i=1;i<=m;i++)    if(dp[i]==i)ans++;printf("%d\n",ans);    }    return 0;}