题目链接:https://cn.vjudge.net/contest/173831#problem/M
题意:给你n种硬币,每种有固定的数量,问你在1到m中能表示几种价格。。
题解:肯定是个DP了,很容易看出来是个多重背包,然后想都没想搞了二级制优化,
发现仍然TLE(感觉自己好弱啊。。)但其实仔细想想你会发现多重背包无非是每一种
金币能多用几次,你唯一不能解决的不就是当前价格表示出来了,但是你不知道用了几个
当前所用该面值金币的数量,呢很好办啊(暴力是会超时的),开一个数组,标记组成该
价格用了多少当前所用该面值金币即可。代码简单,也比二进制优化更省时。。。
#include<map>
#include<stack>
#include<queue>
#include<vector>
#include<math.h>
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
typedef long long ll;
#define inf 1000000000
#define mod 1000000007
#define maxn 100005
#define lowbit(x) (x&-x)
#define eps 1e-10
int dp[maxn],a[maxn],b[maxn],num[maxn];
/*void wanquan(int u,int w,int v)
{
for(int j=u;j<=v;j++)
dp[j]=max(dp[j],dp[j-u]+w);
}
void dan(int u,int w,int v)
{
for(int j=v;j>=u;j--)
dp[j]=max(dp[j],dp[j-u]+w);
}
void work(int u,int w,int num,int v)
{
if(w*num>=v)
wanquan(u,w,v);
else
{
int k=1;
while(k<num)
{
dan(k*u,k*w,v);
num-=k;
k*=2;
}
dan(num*u,num*w,v);
}
}*/
int main(void)
{
int n,m,i,ans,j;
while(scanf("%d%d",&n,&m))
{
ans=0;
if(m==0 && n==0)
break;
memset(dp,0,sizeof(dp));
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
for(i=1;i<=n;i++)
scanf("%d",&b[i]);
dp[0]=1;
for(i=1;i<=n;i++)
{
for(j=0;j<=m;j++)
num[j]=0;
for(j=a[i];j<=m;j++)
{
if(!dp[j] && dp[j-a[i]] && num[j-a[i]]<b[i])
{
num[j]=num[j-a[i]]+1;
dp[j]=1;
ans++;
}
}
}
printf("%d\n",ans);
}
return 0;
}