题目大意:
给定n个物品,第i个物品价值为a[i],数量为c[i],求可以组成的小于m的价值的个数。
思路:
好像n,m的范围比较大,暴力跑二进制优化的多重背包是可以卡过去的。但是有一种
O(nm)
O
(
n
m
)
的方法来优化多重背包,即在枚举体积的时候我们按照完全背包来顺序枚举,完全背包里的枚举体积是可以满足重复选择同意物品的,但是由于每一种物品有自己的数量,所以我们对于每一种体积都记录剩余第i种物品的最大数量,这样就可满足不超出物品数量的限制了。
注意在用滚动数组的时候要把上一层的状态先全部转移到第i层才可以开始DP。
/*=====================
* Author : ylsoi
* Problem : Coins
* Algorithm : DP
* Time : 2018.5.5
* ==================*/
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<climits>
using namespace std;
void File(){
freopen("C1.in","r",stdin);
freopen("C1.out","w",stdout);
}
#define REP(i,a,b) for(register int i=a;i<=b;++i)
#define DREP(i,a,b) for(register int i=a;i>=b;--i)
#define MREP(i,x) for(register int i=beg[x];i;i=E[i].last)
#define mem(a) memset(a,0,sizeof(a))
#define ll long long
#define inf INT_MAX
const int maxn=100+10;
const int maxm=1e5+10;
int n,m,a[maxn],c[maxn],dp[maxm];
int main(){
File();
while(~scanf("%d%d",&n,&m)){
if(n==0 && m==0)break;
memset(dp,-1,sizeof(dp));
dp[0]=0;
REP(i,1,n)scanf("%d",&a[i]);
REP(i,1,n)scanf("%d",&c[i]);
REP(i,1,n){
REP(j,0,m){
if(dp[j]>=0)dp[j]=c[i];//这里即把上一层的状态都转移下来。
else if(j>=a[i] && dp[j-a[i]]>0)dp[j]=dp[j-a[i]]-1;
}
}
int ans=0;
REP(i,1,m)ans+=(dp[i]>=0);
printf("%d\n",ans);
}
return 0;
}