4145:放弃考试 (二分查找)
- 总时间限制:
- 1000ms
- 内存限制:
- 65536kB
- 描述
-
在一门课程中,一共有n场考试。假如你在i场考试中可以答对bi道题中的ai道,那么你的累计平均分定义为:100·Σai/Σbi。已知你这i场考试的答题情况,并且允许你放弃其中的k场考试,请你确定你最高能够得到多少的累计平均分。
假设该课程一共有3门考试,你的答题情况为5/5,0/1和2/6。如果你每门都参加,你的累计平均分为100·(5+0+2)/(5+1+6)= 50分。如果你放弃第3场考试,你的累计平均分则提高到了100·(5+0)/(5+1)= 83.33 ≈ 83分。
- 输入
- 有多组测试数据,每组测试数据包括3行。
每组测试数据第一行有两个数n和k,接下来一行有n个数ai,最后一行n个数bi。
(1 ≤ k < n ≤ 1000) (1 ≤ ai ≤ bi ≤ 1, 000, 000, 000)。
输入的最后一行为0 0,不作处理。 - 输出
- 输出最高的累计平均分。(四舍五入到整数)
- 样例输入
-
3 1 5 0 2 5 1 6 4 2 1 2 7 9 5 6 7 9 0 0
- 样例输出
-
83 100
- 来源
- http://poj.org/problem?id=2976
- 最初的思路是把每一场的胜率排序,从高往底选择前n-k个,但是有正确率为零的场次要带入比较讨论,步骤就比较繁琐。
- 因此直接来个二分查找干。
-
#include <bits/stdc++.h> using namespace std; int a[1005],b[1005],n,k; double ans,y[1005]; bool check(double v) { for(int i=0; i<n; i++) { y[i]=a[i]-v*b[i]; //理解的关键 } sort(y,y+n); double sum=0; for(int i=n-1; i>=k; i--) { sum+=y[i]; } if(sum>=0)return true; else return false; } void fun(){ double left=0,right=1; while(right-left>0.0001){ double mid=left+(right-left)/2; if(check(mid))left=mid; else right=mid; } ans=left*100; } int main() { while(cin>>n>>k&&n!=0) { ans=0; for(int i=0; i<n; i++) { cin>>a[i]; } for(int i=0; i<n; i++) { cin>>b[i]; } fun(); printf("%.0lf\n",ans); } return 0; }
越努力越幸运

浙公网安备 33010602011771号