题解:庆功会
Posted 24Kmagic
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解:庆功会相关的知识,希望对你有一定的参考价值。
题目:
【问题描述】
为了庆贺班级在校运动会上取得全校第一名成绩,班主任决定开一场庆功会,为此拨款购买奖品犒劳运动员。期望拨款金额能购买最大价值的奖品,可以补充他们的精力和体力。
【输入格式】w第一行二个数n(n<=500),m(m<=6000),其中n代表希望购买的奖品的种数,m表示拨款金额。w接下来n行,每行3个数,v、w、s,分别表示第I种奖品的价格、价值(价格与价值是不同的概念)和购买的数量(买0件到s件均可),其中v<=100,w<=1000,s<=10。
解析:
显然,这是一道多重背包的问题,我们可以考虑将其转化成0 1背包问题:
将第i种物品分成若干件物品,其中每件物品有一个系数,这件物品的费用和价值均是原来的费用和价值乘以这个系数。使这些系数分别为1,2,4,...,2(k-1),n[i]-2k+1,且k是满足n[i]-2^k+1>0的最大整数(注意:这些系数已经可以组合出1~n[i]内的所有数字)。例如,如果n[i]为13,就将这种物品分成系数分别为1,2,4,6的四件物品。这样以来我们就可以使用0 1背包的方法做出来这道题了
代码:
#include<bits/stdc++.h>
using namespace std;
int n,m;
int v[10001];
int w[10001];
int s[10001];
int dp[100001] = { };
int cnt[10001] = { };
int main()
{
scanf("%d %d" ,&n,&m);
for(int i = 1;i <= n; i++){
scanf("%d %d %d" ,&v[i],&w[i],&s[i]);
}
for(int i = 1;i <= n; i++){
for(int p = m;p >= v[i]; p--){
for(int k = 1;k <= s[i]; k++){
if(v[i] * k > p) break;
dp[p] = max(dp[p],dp[p - v[i] * k] + w[i] * k);
}
}
}
int ans = 0;
for(int i = 1;i <= m; i++){
ans = max(ans,dp[i]);;
}
printf("%d" ,ans);
return 0;
}
以上是关于题解:庆功会的主要内容,如果未能解决你的问题,请参考以下文章