Bailian4145 放棄考試 POJ2976 ZOJ3068 Dropping tests【二分法+01分數規劃】

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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章