SJTU OJ 1069 二哥的硬币

SJTU OJ 1069 二哥的硬币

原题链接

此题很久之前所写,觉得对于背包问题很有代表意义,就整理一下。
每个面值x的硬币看做价值w=x,占空间v=x的一个物品。根据同面值硬币总值是否超过m分为01背包和完全背包两类。最后判断体积i的背包是否最大能装i价值的硬币,即是否能凑成i面值。
代码如下:

#include <iostream>
#include <cstdio>
using namespace std;
int m, n;
int a[105];
int c[105];
int dp[100005];
int mmax(int x, int y){
    return x>y ? x:y;
}
void complete_bag(int v, int w){
    for (int i=v; i<=m; i++){
        dp[i]= mmax(dp[i], dp[i-v]+w);
    }
}
void zeroone_bag(int v, int w){
    for (int i=m; i>=v; i--){
        dp[i] = mmax(dp[i], dp[i-v]+w);
    }
}
void multi_bag(int v, int w, int c){
    if (v*c>=m){
        complete_bag(v, w);
    }
    else{
        int k=1;
        while (k<c){
            zeroone_bag(k*v, k*w);
            c-=k;
            k*=2;
        }
        zeroone_bag(c*v, c*w);
    }
}
int main()
{
    scanf("%d%d", &n, &m);
    while (!(n == 0 && m == 0)){
        for (int i=1; i<=n; i++){
            scanf("%d", &a[i]);
        }
        for (int i=1; i<=n; i++){
            scanf("%d", &c[i]);
        }
        for (int i=0; i<=m; i++){
            dp[i] = 0;
        }
        for (int i=1; i<=n; i++){
            multi_bag(a[i], a[i], c[i]);
        }
        int countn=0;
        for (int i=1; i<=m; i++){
            if (dp[i]==i){
                countn++;
            }
        }
        printf("%d\n", countn);
        scanf("%d%d", &n, &m);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值