首页 > 其他 > 详细

4145:放弃考试 (二分查找)

时间:2020-03-27 15:47:01      阅读:288      评论:0      收藏:0      [点我收藏+]
总时间限制: 
1000ms
 
内存限制: 
65536kB
描述

在一门课程中,一共有n场考试。假如你在i场考试中可以答对bi道题中的ai道,那么你的累计平均分定义为:100·Σaibi。已知你这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;
}

 

4145:放弃考试 (二分查找)

原文:https://www.cnblogs.com/aiqinger/p/12581104.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!