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
问题链接:Bailian4145 放弃考试 POJ2976 ZOJ3068 Dropping tests
问题简述:给定n和k,有n场考试,给出每场答对的题数a和这场一共有几道题b,计算去掉k场考试后,公式100·Σai/Σbi的最大值。
问题分析:
01分数规划问题:给定价值a[i]和代价b[i],选举n-k个物品,使得总价值/总代价最大。那么算出Σai-xΣbi,去掉k个最小的即可(贪心法)。
需要注意,上式中,因为Σai/Σbi>x相当于Σai-xΣbi>0。
程序说明:(略)
参考链接:(略)
题记:(略)
AC的C++语言程序如下:
/* Bailian4145 放弃考试 POJ2976 ZOJ3068 Dropping tests */
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
const double EPS = 1e-4;
const int N = 1000;
int n, k, a[N], b[N];
double y[N];
bool judge(double x) {
for(int i = 0; i < n; i++) y[i] = a[i] - x * b[i];
sort(y, y + n);
double sum = 0;
for(int i = n - 1; i >= k; i--) sum += y[i];
return sum >= 0;
}
double bs()
{
double left = 0, right = 1, mid;
while(right - left > EPS) {
mid = left + (right - left) / 2;
if(judge(mid)) left = mid;
else right = mid;
}
return mid * 100;
}
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]);
printf("%.0f\n", bs());
}
return 0;
}