• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
dwtfukgv
博客园    首页    新随笔    联系   管理    订阅  订阅
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\n", cnt);
    }
    return 0;
}

 

posted on 2016-05-28 15:39  dwtfukgv  阅读(540)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3