链接:https://www.nowcoder.com/acm/contest/143/A
来源:牛客网
题目描述
Kanade selected n courses in the university. The academic credit of the i-th course is s[i] and the score of the i-th course is c[i].
At the university where she attended, the final score of her is
Now she can delete at most k courses and she want to know what the highest final score that can get.
输入描述:
The first line has two positive integers n,k
The second line has n positive integers s[i]
The third line has n positive integers c[i]
输出描述:
Output the highest final score, your answer is correct if and only if the absolute error with the standard answer is no more than 10-5
示例1
输入
3 1
1 2 3
3 2 1
输出
2.33333333333
说明
Delete the third course and the final score is
备注:
1≤ n≤ 105
0≤ k < n
1≤ s[i],c[i] ≤ 103
先举一个栗子
给定两个数组,a[i]表示选取i的收益,b[i]表示选取i的代价。如果选取i,定义x[i]=1否则x[i]=0。每一个物品只有选或者不选两种方案,求一个选择方案使得R=sigma(a[i]*x[i])/sigma(b[i]*x[i])取得最值,即所有选择物品的总收益/总代价的值最大或是最小。
之后我们设L=R,则有F(L)=sigma(a[i]*x[i])-L*sigma(b[i]*x[i])
=sigma((a[i]-L*b[i])*x[i]
之后记做d[i]=a[i]-L*b[i]
则 F(L)=sigma(d[i])
若F(L)>0 ,则有sigma(a[i]*x[i])/sigma(b[i]*x[i])>R,即有更优解
F(L)<0时没有意义,因为取不到F(L)这个值
F(L)=0即为最优解
同时可知d[i]是单调递减(因为是一元一次方程)
所以通过二分可以找到最优解
——————————————我是分割线——————————————————————————
那么这道题同理,思想相同
R=sigma(s[i]*c[i])/sigma(s[i])
F(L)=sigma(s[i]*c[i])-L*sigma(s[i])
=sigma((c[i]-L)*s[i])
因为F(L)=sigma(d[i])且F(L)=0为最优解
所以计算d[i]并且排序,因为删除k个,并且要保证F(L)越大越好,因为越大越有机会大于0,大于0就可以进一步寻找最优解,所以之后从k开始遍历到最后(数组以0开始)
以下是代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#define require 1e-6
double c[100005],s[100005];
double d[100005];
int main()
{
int num,k;
memset(c,0,sizeof(c));
memset(s,0,sizeof(s));
scanf("%d%d",&num,&k);
for(int i=0;i<num;i++)
scanf("%lf",&s[i]);
double maxn=0;
for(int i=0;i<num;i++){
scanf("%lf",&c[i]);
maxn=max(maxn,c[i]);
}
double l=0,r=maxn;
while(r-l>require){
memset(d,0,sizeof(d));
double mid=(l+r)/2;
for(int i=0;i<num;i++)
d[i]=(c[i]-mid)*s[i];
sort(d,d+num);
double sum=0;
for(int i=k;i<num;i++){
sum+=d[i];
}
if(sum>=0)
l=mid;
else
r=mid;
}
printf("%.6lf\n",l);
}
其中第一段证明参考大佬博客http://www.cnblogs.com/perseawe/archive/2012/05/03/01fsgh.html
后来按照自己的思路写了出来,如有错误之处欢迎指出(~ ̄▽ ̄)~