[模板]最大化平均值

[模板]最大化平均值

给出\(n\)个物品的体积和价值,取\(k\)个物品,使得价值与体积之比最大

考虑二分答案,check(x)表示检查是否存在一个大小为\(k\)的子集使得集合中物品的价值与体积之比\(>=x\)

即$ \frac{\sum v_i}{\sum w_i} \geq x$

移项得 \(\sum v_i \geq \sum w_i · x\)

\(\sum (v_i-w_i · x) \geq 0\)

可以贪心地取前\(k\)大的\(v_i-w_i · x\)值,若总值$ \geq 0$就满足条件,否则不满足条件

取前\(k\)大值可以用\(nth\_element\) \(O(n)\)实现

\(\mathcal{std}\):

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int N=100010;
inline int read(){
	int x=0; char c=getchar();
	while(c<'0') c=getchar();
	while(c>='0') x=(x<<3)+(x<<1)+c-'0',c=getchar();
	return x;
}
int n,k,v[N],w[N];
double p[N];
inline bool check(double x){
	for(int i=1;i<=n;++i)
		p[i]=double(v[i])-x*double(w[i]);
	nth_element(p+1,p+1+n-k,p+1+n);
	double sum=0;
	for(int i=n;i>=n-k+1;--i)
		sum+=p[i];
	return sum>=0;
}
int main()
{
	n=read(),k=read();
	for(int i=1;i<=n;++i)
		w[i]=read(),v[i]=read();
	double l=0,r=1e12;
	while(r-l>1e-7){
		double mid=(l+r)/2.0;
		if(check(mid)) l=mid;
		else r=mid;
	}
	printf("%.5lf\n",l);
	fclose(stdin); fclose(stdout);
	return 0;
}
posted @ 2018-10-31 20:03  yjk  阅读(169)  评论(0编辑  收藏  举报