ybt1269_庆功会

ybt1269_庆功会

时空限制    1000ms/64MB

【题目描述】

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

【输入】

第一行二个数n(n≤500),m(m≤6000),其中n代表希望购买的奖品的种数,m表示拨款金额。

接下来n行,每行3个数,v、w、s,分别表示第I种奖品的价格、价值(价格与价值是不同的概念)和能购买的最大数量(买0件到s件均可),其中v≤100,w≤1000,s≤10。

【输出】

一行:一个数,表示此次购买能获得的最大的价值(注意!不是价格)。

【输入样例】

5 1000
80 20 4
40 50 9
30 50 7
40 30 6
20 20 1

【输出样例】

1040

代码

法一:多重背包朴素算法

#include<iostream>	//朴素算法
#include<algorithm>
using namespace std;
int f[6005];

int main(){
	int n,m;
	cin>>n>>m;
	for (int i=1,v,w,s; i<=n; i++){
		cin>>v>>w>>s;
		for (int j=m; j>=v; j--)	//转换为01背包模式
			for (int k=0; k<=s; k++)
				if (j-k*v>=0) f[j]=max(f[j],f[j-k*v]+k*w);
				else break;
	}
	cout<<f[m]<<endl;
	return 0;
}

法二:二进制优化

#include<iostream>	//优化算法
#include<algorithm>
using namespace std;
const int N = 10005;
int f[6005],price[N],value[N];

int main(){
	int n,m,k=0;
	cin>>n>>m;
	for (int i=1,v,w,s; i<=n; i++){
		cin>>v>>w>>s;
		for (int j=1; j<=s; j*=2){	//用二进制形式存储所有物品价格和价值
			price[++k]=j*v;
			value[k]=j*w;
			s-=j;
		}
		if (s>0) price[++k]=s*v,value[k]=s*w;
	}
	for (int i=1; i<=k; i++)	//01背包求解
		for (int j=m; j>=price[i]; j--)
			f[j]=max(f[j],f[j-price[i]]+value[i]);
	cout<<f[m]<<endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/WDAJSNHC/article/details/81588524