You are to write a program which reads n,m,A1,A2,A3...An and C1,C2,C3...Cn corresponding to the number of Tony's coins of value A1,A2,A3...An then calculate how many prices(form 1 to m) Tony can pay use these coins.
3 10 1 2 4 2 1 1 2 5 1 4 2 1 0 0
8 4
//多重背包转01背包
/*
刚小结完,就把这道题目当做是模板使用吧。
和1077一样,贴上解释。
据背包九讲复杂度是O(V*Σn[i])。
本题的特殊性是价值与重量相等
将第i种物品分成若干件物品,其中每件物品有一个系数,
这件物品的费用和价值均是原来的费用和价值乘以这个系数。
使这些系数分别为1,2,4,…,2^(k-1),n[i]-2^k+1,且k是满足n[i]-2^k+1>0的最大整数。
例如,如果n[i]为13,就将这种物品分成系数分别为1,2,4,6的四件物品。
分成的这几件物品的系数和为n[i],表明不可能取多于n[i]件的第i种物品。
另外这种方法也能保证对于0..n[i]间的每一个整数,均可以用若干个系数的和表示
*/
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <algorithm>
using namespace std ;
int f[100005] ;
int c[105] , num[105] ;
int n , V ;
void ZeroOnePack(int cost,int weight)
{
for (int v=V ; v >= cost ; v --)
f[v]=max(f[v],f[v-cost]+weight) ;
}
void CompletePack(int cost,int weight)
{
for (int v=cost ; v <= V ; v ++ )
f[v]=max(f[v],f[v-cost]+weight) ;
}
void MultiplePack(int cost,int weight,int amount)
{
if ( cost*amount>=V )
{
CompletePack(cost,weight) ;
return ;
}
int k=1 ;
while ( k<amount )
{
ZeroOnePack(k*cost,k*weight) ;
amount=amount-k ;
k=k*2 ;
}
ZeroOnePack(amount*cost,amount*weight) ;
}
int main()
{
while(scanf("%d %d", &n , &V ) && n != 0 && V != 0 )
{
for(int i = 1 ; i <= n ; i ++ )
{
scanf( "%d",&c[i]) ;
}
for(int i = 1 ; i <= n ; i ++ )
{
scanf( "%d",&num[i]) ;
}
memset(f,0,sizeof(f)) ;
for(int i = 1 ; i <= n ; i ++)
{
MultiplePack(c[i],c[i],num[i]) ;
}
int ans = 0 ;
for(int i = 1 ; i <= V ; i ++)
{
if(f[i] == i) ans ++ ;
}
printf("%d\n",ans) ;
}
}