题目链接:http://poj.org/problem?id=1742
题目大意:有一系列硬币,每种硬币都有自己的数量,要求这些硬币能在1 - m之间组成多少种面值。
分析:多重背包的变形,在多重背包的同时加一个标记数组,只要该面值出现过,记录下来就可以,下次再出现直接continue;
ac代码:
#include<cstdio>
#include<string.h>
#define M 100005
#define N 105
int A[N], C[N];
int count[M];
bool flag[M];
int main()
{
int n, m;
while(scanf("%d %d", &n, &m))
{
if(n == 0 && m == 0)break;
for(int i = 1; i <= n; i++)
scanf("%d", &A[i]);
for(int i = 1; i <= n; i++)
scanf("%d", &C[i]);
for(int i = 1; i <= m; i++)
flag[i] = false;
flag[0] = true;
for(int i = 1; i <= n; i++)
{
memset(count, 0, sizeof(count));
for(int j = A[i]; j <= m; j++)
{
if(flag[j])continue;
if(flag[j - A[i]] && count[j - A[i]] < C[i])
{
flag[j] = true;
count[j] = count[j - A[i]] + 1;
}
}
}
int ans = 0;
for(int i = 1; i <= m; i++)
if(flag[i])ans++;
printf("%d\n", ans);
}
return 0;
}