poj2976 Dropping tests(二分法:最大化平均值)

题目链接:https://vjudge.net/problem/POJ-2976

题目大意:你有一份成绩单,你可以丢弃k门课程,让你的平均分更高,你一共n门课程的成绩

题目思路:你可能会想到贪心,背包这类的方法,但是解决最大化平均值这类问题的最好方法便是二分法。

我对最大平均成绩进行二分mid,每门课程的成绩为v[i]所占权重就是w[i],那么每门课程的贡献值为con[i] = v[i]-x*w[i],我再对con[]数组进行排序(从大到小)最后我再选取(n-k)个进行求和,看看最后的sum值是否大于0。

学到的东西:二分可以解决很多问题,做题要多动脑。

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 1e5+10;
const int inf = 1e9+7;
int n,k;
double v[maxn],w[maxn],con[maxn];
bool cmp(int a,int b)
{
    return a>b;
}

bool judge(double mid)
{
    for(int i=0;i<n;i++)
        con[i]=v[i]-mid*w[i];

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

    if(sum>=0) return true;

    return false;
}

int main()
{
    while(scanf("%d%d",&n,&k)){
        if(n==0&&k==0) break;

        for(int i=0;i<n;i++) scanf("%lf",&v[i]);
        for(int i=0;i<n;i++) scanf("%lf",&w[i]);

        double l=0,r=inf,mid;
        int num=100;
        while(num--){ //避免精度问题
            mid=(l+r)/2;
            if(judge(mid)) l=mid;
            else r=mid;
        }

        printf("%.0f\n",l*100);
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值