Dropping tests 放弃测试 二分法 最大化平均值

原题:

          放弃一些测试

题目描述:

今年有 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 ≤ kn。第二行有 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;
} 

猜你喜欢

转载自blog.csdn.net/error311/article/details/81265480
今日推荐