题解:庆功会

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;
}

以上是关于题解:庆功会的主要内容,如果未能解决你的问题,请参考以下文章

庆功会

庆功会(多重背包)

边缘计算深度交流会暨StarlingX2.0发布庆功会召开在即

大数据时代,分布式存储与智慧城市精英峰会系列报道——孟庆功

敏捷开发总结

Java 求解划分字母区间