庆功会

本文介绍了一个多重背包问题的实例——班级庆功会奖品选购问题,并提供了两种解决方案:01背包算法和多重背包算法。通过具体代码展示了如何解决这类问题,为读者提供了一种解决多重背包问题的有效途径。

Description

nyzoj10032

为了庆贺班级在校运动会上取得全校第一名成绩,班主任决定开一场庆功会,为此拨款购买奖品犒劳运动员。期望拨款金额能购买最大价值的奖品,可以补充他们的精力和体力。

Analysis

这题是多重背包模板题,但我也只能找到这个难度的了..

值得一提的是多重背包的拆分过程中不能用log2直接算...误差有点大,会RE70。

Code 01背包

#include <bits/stdc++.h>
const int N=6010;
int n,m,c[N],v[N],s[N],dp[N];
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d%d%d",&c[i],&v[i],&s[i]);
    for(int i=1;i<=n;i++)
        for(int j=m;j>=1;j--)
            for(int k=1;k<=std::min(j/c[i],s[i]);k++)
                dp[j]=std::max(dp[j],dp[j-k*c[i]]+k*v[i]);
    printf("%d\n",dp[m]);
    return 0;
}

Code 多重背包

#include <bits/stdc++.h>
const int N=6010;
int n,m,dp[N];
struct award{
    int c,v;
};
std::vector <award> a;
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        int c,v,s,k;
        scanf("%d%d%d",&c,&v,&s);
        award temp;
        for(k=0;;k++,a.push_back(temp)){
            if(s<(1<<k+1)-1)break;
            temp.c=(1<<k)*c;
            temp.v=(1<<k)*v;
        }
        temp.c=(s-(1<<k)+1)*c;
        temp.v=(s-(1<<k)+1)*v;
        a.push_back(temp);
    }
    for(int i=0;i<a.size();i++)
        for(int j=m;j>=a[i].c;j--)
            dp[j]=std::max(dp[j],dp[j-a[i].c]+a[i].v);
    printf("%d\n",dp[m]);
    return 0;
}

转载于:https://www.cnblogs.com/qswx/p/9607503.html

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值