[模板]最大化平均值

[模板]最大化平均值

给出\(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;
}

转载于:https://www.cnblogs.com/yjkhhh/p/9885259.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值