HDU 2844 Coins (多重背包问题DP)

题意:给定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;
}
原文地址:https://www.cnblogs.com/dwtfukgv/p/5537556.html