Description
n场考试中分别答对ai题,总题数分别为bi,允许去掉k场考试,求能达到的最高准确率
Input
多组用例,每组用例第一行为两个整数n和k分别表示考试次数和可去考试次数,第二行为每次考试答对的题数,第三行为每次考试的总题数,以n=k=0结束输入
Output
对于每组用例,输出去掉k次考试后的最高准确率
Sample Input
3 1
5 0 2
5 1 6
4 2
1 2 7 9
5 6 7 9
0 0
Sample Output
83
100
Solution
需要确定一个贪心策略,每次贪心地去掉那些对正确率贡献小的考试。如何确定某个考试[ai, bi]对总体准确率x的贡献呢?ai / bi肯定是不行的,不然例子里的[0,1]会首当其冲被刷掉。在当前准确率为x的情况下,这场考试“额外”对的题目数量是ai – x * bi,当然这个值有正有负,恰好可以作为“贡献度”的测量。于是利用这个给考试排个降序,后k个刷掉就行了
Code
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
#define maxn 10005
#define eps 1e-4
int a[maxn],b[maxn];
int n,k;
double C(double x)
{
double ans=0,d[maxn];
for(int i=0;i<n;i++)
{
ans+=1.0*100*a[i]-1.0*x*b[i];//额外对的题
d[i]=1.0*100*a[i]-1.0*x*b[i];
}
sort(d,d+n);//对每次考试的贡献排序
for(int i=0;i<k;i++)//减去贡献最少的
ans-=d[i];
return ans>-eps;
}
int main()
{
while(scanf("%d%d",&n,&k)&&(n||k))
{
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
for(int i=0;i<n;i++)
scanf("%d",&b[i]);
double l=0,r=100,ans=-1;//x是百分比,所以l=0,r=100
while(r-l>eps)
{
double mid=(l+r)/2;
if(C(mid))
l=ans=mid;
else
r=mid;
}
printf("%.lf\n",ans);
}
return 0;
}