思路:多重背包,dp[i]表示价格总数为i能凑出来的最大价格,比模板多了的唯一一点是查多少数字出现过,枚举一遍dp[i]==i的个数。
#include<bits/stdc++.h> using namespace std; #define inf 0x3f3f3f3f #define ll long long #define fo freopen("in.txt","r",stdin) #define fc fclose(stdin) #define fu0(i,n) for(i=0;i<n;i++) #define fu1(i,n) for(i=1;i<=n;i++) #define fd0(i,n) for(i=n-1;i>=0;i--) #define fd1(i,n) for(i=n;i>0;i--) #define mst(a,b) memset(a,b,sizeof(a)) #define sd(n) scanf("%d",&n) #define sdd(n,m) scanf("%d %d",&n,&m) #define ss(s) scanf("%s",s) #define sddd(n,m,k) scanf("%d %d %d",&n,&m,&k) #define pans() printf("%d\n",ans) #define all(a) a.begin(),a.end() #define sc(c) scanf("%c",&c) #define we(a) while(scanf("%d",&a)!=EOF) const int maxn=200005; const double eps=1e-8; int dp[maxn]; int n,m; void zeroonepack(int w,int v)//w:重量,v:价值 { for(int i=m;i>=w;i--) { dp[i]=max(dp[i],dp[i-w]+v); } } void completepack(int w,int v) { for(int i=w;i<=m;i++) { dp[i]=max(dp[i],dp[i-w]+v); } } void multipack(int w,int v,int num) { if(w*num>=m) { completepack(w,v); } else { int k=1; while(k<num) { zeroonepack(k*w,k*v); num-=k; k<<=1; } zeroonepack(num*w,num*v); } } int main() { while(cin>>n>>m) { if(!m&&!n) break; memset(dp,0,sizeof(dp)); int i,j,a[105],c[105]; for(i=0;i<n;i++) { cin>>a[i]; } for(i=0;i<n;i++) { cin>>c[i]; } for(i=0;i<n;i++) { multipack(a[i],a[i],c[i]); } int count=0; for(int i=1;i<=m;i++) { if(dp[i]==i) count++; } cout<<count<<endl; } return 0; }