题意:给定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; }