题目大意:有N种货币v1,v2,v3,…,vn,每种有c1,c2,c3,…,cn个,求这些货币在不超过m的情况下能组成多少种面值
分析:多重背包。背包问题还不怎么熟,看了下别人的题解,大致的意思是,只有当面值j-v[i]出现过,面值j才能出现,并且货币i的使用次数不能超过c[i]
状态:d[j]表示面值为j的情况
状态转移:if(!dp[j] && dp[j-v[i]] && sum[j-v[i]] < c[i]) {
dp[j] = 1;
sum[j] = sum[j-v[i]] + 1;
ans++;
}
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int main() {
int n, m;
int v[105], c[105];
while(scanf("%d%d", &n, &m) && n != 0) {
for(int i = 0; i < n; i++)
scanf("%d", &v[i]);
for(int i = 0; i < n; i++)
scanf("%d", &c[i]);
int sum[100005], ans = 0, dp[100005];
memset(dp, 0, sizeof(dp));
dp[0] = 1;
for(int i = 0; i < n; i++) {
memset(sum, 0, sizeof(sum));
for(int j = v[i]; j <= m; j++) {
if(!dp[j] && dp[j-v[i]] && sum[j-v[i]] < c[i]) {
dp[j] = 1;
sum[j] = sum[j-v[i]] + 1;
ans++;
}
}
}
printf("%d\n", ans);
}
return 0;
}