POJ 2976 Dropping tests【0/1分数规划模板】

传送门:http://poj.org/problem?id=2976

题意:给出na_ib_i,去掉k对数据,使得a_i的总和除以b_i的总和最大。

思路:0/1分数规划

ans=sum a_i*x_i/sum b_i*x_i,则sum a_i*x_i-ans*sum b_i*x_i=0
ightarrowx_i*sum (a_i-ans*b_i)=0(其中x_i等于0或1)

开始假设ans使得上式成立,将s_i=a_i-ans*b_i从大到小排序,只取前n-k个(这样一定是最优的),若所得和大于0,则表示ans偏小,反之偏大。

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
const double eps = 1e-7;
int a[1005];
int b[1005];
double s[1005];
int n, k;
double solve(double x)
{
    for(int i = 1; i <= n; i++)
        s[i] = a[i] - x * b[i];
    sort(s + 1, s + 1 + n);
    double sum = 0;
    for(int i = k + 1; i <= n; i++)
        sum += s[i];
    return sum;
}
int main()
{
    while(~scanf("%d%d", &n, &k) && (n + k))
    {

        for(int i = 1; i <= n; i++)
        {
            scanf("%d", &a[i]);
        }
        for(int i = 1; i <= n; i++)
            scanf("%d", &b[i]);
        double l = 0, r = 1;
        double mid ;
        while((r - l) > eps)
        {
            mid = (l + r) / 2;
            if(solve(mid) > 0)
            {
                l = mid;
            }
            else
            {
                r = mid;
            }
        }
        printf("%0.lf
", mid * 100 );
    }
    return 0;
}
原文地址:https://www.cnblogs.com/yyaoling/p/12260413.html