[多重背包问题] 硬币

硬币

给定N种硬币,其中第 i 种硬币的面值为Ai,共有Ci个。
从中选出若干个硬币,把面值相加,若结果为S,则称“面值S能被拼成”。
求1~M之间能被拼成的面值有多少个。
输入格式
输入包含多组测试用例。
每组测试用例第一行包含两个整数N和M。
第二行包含2N个整数,分别表示A1,A2,…,AN和C1,C2,…,CN。
当输入用例N=0,M=0时,表示输入终止,且该用例无需处理。
输出格式
每组用例输出一个结果,每个结果占一行。】
数据范围
1≤N≤100,
1≤M≤105,
1≤Ai≤105,
1≤Ci≤1000
输入用例:
3 10
1 2 4 2 1 1
2 5
1 4 2 1
0 0
输出用例:
8
4


多重背包问题


#include
using namespace std;
const int maxn = 100000;

int dp[maxn];
int a[101], c[101];
int f[maxn];

int main  () {
    int n, m;
    cin >> n >> m;
    while (n != 0 && m != 0) {
        for (int i = 1; i <= m; i++)    dp[i] = 0;
        for (int i = 1; i <= n; i++)    cin >> a[i];
        for (int i = 1; i <= n; i++)    cin >> c[i];
        dp[0] = 1;
        for (int i = 1; i <= n; i++) {
            int s1 = a[i], s2 = c[i];
            for (int j = 1; j <= m; j++)    f[j] = 0;
            for (int j = s1; j <= m;j++) {
                if (dp[j - s1] == 1 && f[j - s1] < s2 && dp[j] != 1) {
                    dp[j] = 1;
                    f[j] = f[j - s1] + 1;
                }
            }
        }
        int cnt = 0;
        for (int i = 1; i <= m; i++) {
            if (dp[i] != 0) {
                cnt ++;
            }
        }
        cout << cnt << "\n";
        cin >> n >> m;
    }
}


你可能感兴趣的:([多重背包问题] 硬币)