题意:给定n种硬币,每种价值是a,数量是c,让你求不大于给定V的不同的价值数,就是说让你用这些硬币来组成多少种不同的价格,并且价格不大于V。
析:一看就应该知道是一个动态规划的背包问题,只不过是变形,那我们就统计不大于V的不同价格数,也容易实现,
对于多重背包我们是把它转化为01背包和完全背包来解决的。
代码如下:
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
typedef long long LL;
const int maxn = 100000 + 10;
int d[maxn];
int c[maxn], a[maxn], V;
void zeroonepack(int v, int val){
for(int i = V; i >= v; --i)
d[i] = max(d[i], d[i-v]+val);
}
void completepack(int v, int val){
for(int i = v; i <= V; ++i)
d[i] = max(d[i], d[i-v]+val);
}
void multiplepack(int v, int val, int num){
if(V <= num * v){ completepack(v, val); return ; }
int k = 1;
while(k <= num){
zeroonepack(v*k, val*k);
num -= k;
k <<= 1;
}
zeroonepack(num*v, num*val);
}
int main(){
int n;
while(scanf("%d %d", &n, &V)){
if(!n && !V) break;
for(int i = 0; i < n; ++i) scanf("%d", &a[i]);
for(int i = 0; i < n; ++i) scanf("%d", &c[i]);
memset(d, 0, sizeof(d));
for(int i = 0; i < n; ++i)
multiplepack(a[i], a[i], c[i]);
int cnt = 0;
for(int i = 1; i <= V; ++i)
if(d[i] == i) ++cnt;
printf("%d
", cnt);
}
return 0;
}