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;
}