poj 2976 Dropping tests 【0-1分数规划】

Dropping tests
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 7828   Accepted: 2739

Description

In a certain course, you take n tests. If you get ai out of bi questions correct on test i, your cumulative average is defined to be

.

Given your test scores and a positive integer k, determine how high you can make your cumulative average if you are allowed to drop any k of your test scores.

Suppose you take 3 tests with scores of 5/5, 0/1, and 2/6. Without dropping any tests, your cumulative average is . However, if you drop the third test, your cumulative average becomes .

Input

The input test file will contain multiple test cases, each containing exactly three lines. The first line contains two integers, 1 ≤ n ≤ 1000 and 0 ≤ k < n. The second line contains n integers indicating ai for all i. The third line contains n positive integers indicating bi for all i. It is guaranteed that 0 ≤ ai ≤ bi ≤ 1, 000, 000, 000. The end-of-file is marked by a test case with n = k = 0 and should not be processed.

Output

For each test case, write a single line with the highest cumulative average possible after dropping k of the given test scores. The average should be rounded to the nearest integer.

Sample Input

3 1
5 0 2
5 1 6
4 2
1 2 7 9
5 6 7 9
0 0

Sample Output

83
100

Hint

To avoid ambiguities due to rounding errors, the judge tests have been constructed so that all answers are at least 0.001 away from a decision boundary (i.e., you can assume that the average is never 83.4997).


题意:给你N个二元组(a[i], b[i]),你可以从里面任意去掉K个。问你100 * sigma(a[i]) / sigma(b[i])的最大值。


以前做过一道类似的题目 ,看了别人题解AC之后就放那里了。现在看最小割,也用到分数规划,没办法只好看了。


分析:我们假设存在一种方案使得 o = sigma(a[i]) / sigma(b[i]) 的值 是最大的,我们可以转化这个式子并新设一个函数——sigma(t[i]) = sigma(a[i]) - sigma(b[i]) * o 。

切记,我们假设最大的o = sigma(a[i]) / sigma(b[i])才新设函数t[i]的。

这样的话,当o取最大值时,会满足sigma(t[i]) = 0。

反过来说sigma(t[i]) > 0时,说明当前的o不是最大的,还可以继续增大。

sigma(t[i]) < 0 时,说明当前的o过大,是不能满足的。



思路:二分枚举o的值,用当前的o值求出所有的t[i],累加最大的N-K个,判断这N-K个t[i]的值是否大于0。若大于0继续增大o值,小于o则减小o值。



AC代码:



#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define eps 1e-8
#define MAXN 1010
using namespace std;
int N, K;
double a[MAXN], b[MAXN];
double t[MAXN];
bool judge(double o)
{
    for(int i = 0; i < N; i++)//求t[i]
        t[i] = a[i] - o * b[i];
    sort(t, t+N);//排序后
    double sum = 0;
    for(int i = K; i < N; i++)//累加最大的N-K个
        sum += t[i];
    return sum >= 0;
}
int main()
{
    while(scanf("%d%d", &N, &K), N||K)
    {
        for(int i = 0; i < N; i++)
            scanf("%lf", &a[i]);
        for(int i = 0; i < N; i++)
            scanf("%lf", &b[i]);
        double l = 0, r = 1;
        while(r - l >= eps)
        {
            double mid = (l + r) / 2;
            if(judge(mid))
                l = mid;
            else
                r = mid;
        }
        printf("%.0lf\n", l * 100);
    }
    return 0;
}


你可能感兴趣的:(poj 2976 Dropping tests 【0-1分数规划】)