题目链接: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);
}
}