题意:一个人有一些硬币,给定了硬币的价值和数量,问他能组成多少种和 。
明显的多重背包
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
int d[100000+10],n,m;
int w[105],c[105];
int vis[100000+10];
void zeroonepack(int w,int p)
{
for(int i=m;i>=w;i--)
if(d[i]<d[i-w]+p) d[i]=d[i-w]+p;
}
void completepack(int w,int p)
{
for(int i=w;i<=m;i++)
if(d[i]<d[i-w]+p) d[i]=d[i-w]+p;
}
void multipack(int w,int p,int c)
{
if(w*c>=m) completepack(w,p);
else
{
int k=1;
while(k<c)
{
zeroonepack(k*w,k*p);
c-=k;
k*=2;
}
zeroonepack(c*w,c*p);
}
}
int main()
{
while(scanf("%d%d",&n,&m))
{
if(n==0||m==0) break;
memset(d,0,sizeof(d)); int ans = 0;
memset(vis,0,sizeof(vis));
for(int i=0;i<n;i++) scanf("%d",&w[i]);
for(int i=0;i<n;i++) scanf("%d",&c[i]);
for(int i=0;i<n;i++) multipack(w[i],w[i],c[i]);
for(int i=1;i<=m;i++) vis[d[i]] = 1;
for(int i=1;i<=m;i++) if(vis[i]) ans++;
printf("%d\n",ans);
}
}