贪心算法 部分背包问题 public-13 by mrhao61

http://noip.hrbeu.edu.cn/problem/13
时间限制 内存限制 总提交数 AC数 Special Judge 题目类型 学校名称 最近更新时间
10s 128m 89 35 否 NOIP public 8个月前
Description
某天John到了一个岛上,上面有许多珍贵的金属,他只带着一个口袋,口袋至多只能装重量为w的物品。岛上金属有s个种类, 每种金属重量不同,分别为n1,n2,…,ns,同时每个种类的金属总的价值也不同,分别为v1,v2,…,vs。John想一次带走价值尽可能多的金属,问他最多能带走价值多少的金属。金属是可以被任意分割的,并且金属的价值和其重量成正比。

Input
第1行是测试数据的组数k,后面跟着k组输入。每组测试数据占3行,第1行是一个正整数w(1≤w≤10000) ,表示口袋承重上限。第2行是一个正整数s(1≤s≤100),表示金属种类。第3行有2s个正整数,分别为n1,v1,n2,v2,…,ns,vs分别为第1种,第2种,…,第s种金属的总重量和总价值(1≤ni,vi≤10000) 。

Output
k行,每行输出对应一个输入。输出应精确到小数点后2位。

Sample Input
2
50
4
10 100 50 30 7 34 87 100
10000
5
1 43 43 323 35 45 43 54 87 43

Sample Output
171.93
508.00

Hint
Source
Author

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define max 10005
using namespace std;
struct mmetal
{
	double vh;
	int v;
	int n;
}metal[max];
bool cmp(const mmetal &a, const mmetal &b)
{
    return a.vh<b.vh;
}
int main()
{
	int k;cin>>k;
	while(k--)
	{
		double w;
		int s;cin>>w>>s;
		memset(metal,0,sizeof(metal));
		for(int i=1;i<=s;i++)
		{
			cin>>metal[i].n>>metal[i].v;
			metal[i].vh=metal[i].v/metal[i].n;
		}
		sort(metal+1,metal+s+1,cmp);
		double ans=0;
		for(int i=s;i>0;i--)
		{
			if(w>metal[i].n)
			{
				w-=metal[i].n;
				ans+=metal[i].v;
			}
			else
			{
				ans+=w*metal[i].v/metal[i].n;break;
			}
		}	
		printf("%.2f\n",ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43870649/article/details/88803300