最大化平均值 (二分搜索法)

题目描述:

有n个物品的重量和价值分别为Wi和Vi。从中选出k个物品使得单位重量的价值最大。

例如:
n=3
k=2
(w,v)={(2,2) , (5,3) , (2,1) }

输出应为0.75

分析:
一般我们最先想到的就是把物品按照单位价值进行排序,从大到小贪心的进行选取。但是这种方法对于样例的输出应该为5/7=0.714,所以这个方法是不行的。

这个问题应该使用二分搜索法解决,定义:
C(x),表示,可以选择的单位重量的价值不小于x

我们要求满足C(x)的最大的x,

单位重量的价值为:Vi / Wi

Vi / Wi>=x.

即C(x)=(Vi -x Wi),从大到小排序中的钱k个的和不小于0.

代码:

#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
int n,k;
int w[10009],v[10009];
double y[10009];
bool cmp(double a,double b)
{
    return a>b;
}
bool C(double x)
{
   for(int i=0;i<n;i++)
        y[i]=v[i]-x*w[i];

   sort(y,y+n,cmp);
   double sum=0;
   for(int i=0;i<k;i++)
    sum+=y[i];

   return sum>=0;
}

void solve()
{
    double lb=0,ub=0x3f3f3f3f;
    for(int i=0;i<100;i++)
    {
        double mid=(lb+ub)/2;
        if(C(mid)) lb=mid;
        else
            ub=mid;
    }
    printf("%.2lf
",ub);
}
int main()
{
    scanf("%d%d",&n,&k);
    for(int i=0;i<n;i++)
        scanf("%d%d",&w[i],&v[i]);
    solve();
    return 0;
}
原文地址:https://www.cnblogs.com/cmmdc/p/7207895.html