Dropping tests(最大化平均值)

题目链接:https://cn.vjudge.net/contest/279225#problem/G
题目大意:就是b个问题得了a分,问最大化平均值。现在要去掉k个test的信息之后重新算平均值,问去掉哪些之后剩下的平均值最大。
其实这个需要就是推个公式:100∑a[i] /∑b[i],我们现在不是要用二分来找答案吗,所以看x行不行。
先想一下,如果x是我们要找的最大平均值的话,那么100∑a[i] /∑b[i]这个式子就是要大于等于x。因为想一下,如果小于x的话,那么平均值是达不到x的,所以如果等于的话,说明这个x可行,但是不一定是最大的,所以要往右取,如果大于的话就说明这个x太小了,需要往右再取大一点。
100∑a[i] / ∑b[i]>=x,
整理一下就是∑100 a[i] >=∑b[i] * x,
再整理一下就是∑ (100a[i]-b[i]*x)>=0,
所以我们要找到最大化平均值的话,每个单项也就是100a[i]-b[i]*x越大,就平均值越大,所以我们对100a[i]-b[i]*x排序,然后取前n-k项的和
所以如果n-k个100a[i]-b[i]*x的和大于等于0的话,x就是可行解
所以实际上这个左区间上是可行解,右区间上是不可行解

还有一点要说的就是,这个平均值因为是约数,题目上给的就是约数,约数是四舍五入的,而都double本身取整的时候或者取几位小数的时候会自动取四舍五入,所以直接把答案输出0位小数的实型就直接是我们要的答案。

#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
using namespace std;
double n,k;
struct node
{
    double a,b,value;
};
node mm[1005];
bool cmp(const node &n1,const node &n2)
{
    return n1.value>n2.value;
}
bool judge(double x)
{
    double ans=0;
    for(int i=0;i<n;i++)
    {
        mm[i].value=100*mm[i].a-mm[i].b*x;//因为每次的x都不一样,所以每次都要重新依据这个排序
    }
    sort(mm,mm+(int)n,cmp);
    for(int i=0;i<n-k;i++)
    {
        ans+=mm[i].value;
    }
    return ans>=0;
}
int main()
{
    while(~scanf("%lf%lf",&n,&k)&&(n||k))
    {
        for(int i=0;i<n;i++)
        {
            scanf("%lf",&mm[i].a);
        }
        for(int i=0;i<n;i++)
        {
            scanf("%lf",&mm[i].b);
        }
        double max_,min_,mid;
        min_=0;max_=100;//因为这个平均值是在0到100之间的,所以就直接取这个区间就可
        while(max_-min_>=1e-8)//因为是浮点型数据,所以还是要取这个精度
        {
            mid=(max_+min_)/2;
            if(judge(mid))
                min_=mid;
            else
                max_=mid;
        }
        printf("%.0f\n",max_);//最后这个其实取max_,min_,mid都是一样的,因为前边我们的精度很大了,所以这三个数值最后相差的之后后边的小数位数,前边都是一样的,然后double自动四舍五入取整就是我们要的答案
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44049850/article/details/86562201
今日推荐