POJ2976 Dropping tests

2017年8月7日

链接:http://poj.org/problem?id=2976

这是道01分数规划的入门题.给你 n 个数 a_ib_i,让你从中取出 n – k 对 a_ib_i,使 \\frac{\\sum{a}}{\\sum{b}} 的值最大.

\\lambda=\\frac{\\sum{a}}{\\sum{b}},则题目就是求\\lambda的最大值,变形就有 \\sum{a}-\\lambda\\sum{b}=0

g(\\lambda)=\\max(\\sum{a}-\\lambda\\sum{b})=\\max(\\sum{(a-\\lambda b})),可证g(\\lambda)是个单调递增函数.

而当 g(\\lambda)=0时,可取得 \\lambda的最大值,所以只需二分\\lambda的值,代入即可.

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const double eps = 1e-7;
const int N = 1005;
int n, k;
double mid;
struct node {
    int a, b;
    bool operator < (const node &op) const {
        return 1.0 * (a - mid * b) > 1.0 * (op.a - mid * op.b);
    }
} e[N];
int main()
{
    while (~scanf("%d %d", &n, &k) && (n + k)) {
        for (int i = 0; i < n; i++) {
            scanf("%d", &e[i].a);
        }
        for (int i = 0; i < n; i++) {
            scanf("%d", &e[i].b);
        }
        double low = 0.0, high = 1.0;
        double ans = 0;
        while (high - low > eps) {
            mid = (low + high) / 2;
            sort(e, e + n);
            long long suma = 0, sumb = 0;
            for (int i = 0; i < n - k; i++) {
                suma += e[i].a;
                sumb += e[i].b;
            }
            double tmp = 1.0 * suma - mid * sumb;
            ans = 1.0 * suma / sumb;
            if (tmp < 0) {
                high = mid;
            } else {
                low = mid;
            }
        }
        printf("%.f\n", ans * 100);
    }
    return 0;
}

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注