HDU-2844 Coins 多重背包 物品数量二进制优化

题目链接:https://cn.vjudge.net/problem/HDU-2844

题意

给你一些不同价值和一定数量n的硬币。
求用这些硬币可以组合成价值在[1 , m]之间的有多少。

思路

多重背包问题,看了一眼数据范围,用二进制优化一下物品数量即可。

提交过程

AC

代码

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=100+20, maxm=1e5;
int num[maxn], cost[maxn], val[maxn];
int dp[maxm];
int n, m;

void zeroKnap(int cost, int val){
    for (int i=m; i>=cost; i--)
        dp[i]=max(dp[i], dp[i-cost]+val);
}

void compKnap(int cost, int val){
    for (int i=cost; i<=m; i++)
        dp[i]=max(dp[i], dp[i-cost]+val);
}

int main(void){
    while (scanf("%d%d", &n, &m)==2 && n+m){
        for (int i=1; i<=n; i++) scanf("%d", &cost[i]);
        for (int i=1; i<=n; i++) scanf("%d", &num[i]);

        memset(dp, 0, sizeof(dp));
        for (int i=1; i<=n; i++){
            if (num[i]*cost[i]>=m)
                compKnap(cost[i], cost[i]);
            else{
                for (int k=1; k<num[i]; k*=2){
                    zeroKnap(cost[i]*k, cost[i]*k);
                    num[i]-=k;
                }
                zeroKnap(cost[i]*num[i], cost[i]*num[i]);
            }
        }

        int ans=0;
        for (int i=1; i<=m; i++)
            if (dp[i]==i) ans++;
        printf("%d
", ans);
    }
    
    return 0;
}

Time Memory Length Lang Submitted
234ms 1596kB 1108 G++ 2018-08-21 05:13:40
原文地址:https://www.cnblogs.com/tanglizi/p/9513819.html