POJ1742---Coins

题目大意:有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;
}

你可能感兴趣的:(poj)