原题:
题目描述:
今年有 n 场 ACM-ICPC 竞赛,小明每场都有资格参加。第 i 场竞赛共有 b[i] 道题。小明预测第 i 场他能做出 a[i] 道题。为了让自己看着更“大佬”一些,小明想让自己平均做出的题数越大越好,也就是最大化大佬度,大佬度的定义如下:
为了达到这个目的,小明决定放弃 k 场比赛的参赛资格。请求出最大的大佬度。
例如有 3 场小型比赛,题数分别是 5 题、1 题、6 题,小明预测自己分别能做出 5 题、0题、2题。如果每场都参加,那么大佬度是 ,看着不怎么大佬。不过,如果放弃第 3 场比赛,那么大佬度就是 ,看着更加大佬了。
Input
输入测试文件含有多组测试,每组有 3 行。第一行有 2 个整数, 1 ≤ n ≤ 1000 和 0 ≤ k< n。第二行有 n 个整数,即每个 a[i]。第三行含有 n 个正整数 b[i]。保证 0 ≤ a[i] ≤ b[i] ≤ 1, 000, 000, 000。文件末尾由 n = k = 0 标识,并且不应该被处理。
Output
对于每组测试数据,输出一行整数,即放弃 k 场比赛后可能的最高大佬度。
解题思路:
要注意这题不能用单位价值的排序来求答案是错的
使用二分法,求其平均值。sum( a ) / sum( b ) >=x ; 则 sum( a-x*b ) >= 0 ;
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 1005;
int a[maxn],b[maxn];
double c[maxn];
int n,k;
bool ok(double ans){
for(int i = 0;i < n;i++){
c[i] = a[i] - ans / 100 * b[i] ; //第i个的平均值 a[i]/b[i] = ans
}
sort(c,c+n);
double sum = 0;
for(int i = 0;i < n - k;i++){ // n - k 抛弃 K 个数
sum += c[n-1-i]; // 从后往前,后面的值大,
}
return sum >= 0; //ans这个平均值应该满足的条件
}
int main(){
while(scanf("%d%d",&n,&k) != EOF){
if(n == 0 && k == 0){
break;
}
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 = 105;
for(int i = 0;i < 100;i++){
double mid = (l + r) / 2; //二分法求平均值
if(ok(mid)){
l = mid;
}
else{
r = mid;
}
}
printf("%.0f\n",r);
}
return 0;
}