天天看点

poj2976 Dropping tests 【01分数规划】

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

题意:给你n个a和b,让你求删掉其中的k对使得 sigma(a[i])/sigma(b[i])最大。

分析:01分数规划第一题,看这篇可以有个大概的了解。关键点在于不容易求一个值,但是验证某个值可行很容易。

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define INF 0x3f3f3f3f
#define Mn 1010
#define Mm 2000005
#define mod 1000000007
#define CLR(a,b) memset((a),(b),sizeof((a)))
#define CLRS(a,b,Size) memset((a),(b),sizeof((a[0]))*(Size+1))
#define CPY(a,b) memcpy ((a), (b), sizeof((a)))
#pragma comment(linker, "/STACK:102400000,102400000")
#define ul u<<1
#define ur (u<<1)|1
#define eps 1e-5
using namespace std;
typedef long long ll;
double a[Mn],b[Mn],d[Mn];
int n,m;
bool check(double x) {
    double sum=0;
    for(int i=0;i<n;i++) d[i]=a[i]-x*b[i];
    sort(d,d+n);
    for(int i=m;i<n;i++) sum+=d[i];
    if(sum>0) return true;
    else return false;
}
int main() {
    while(~scanf("%d%d",&n,&m)) {
        if(n==0&&m==0) break;
        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.0,r=1.0;
        while(l+eps<r) {
            double mid=(l+r)/2;
            if(check(mid)) l=mid;
            else r=mid;
        }
        printf("%.0f\n",100*l);
    }
    return 0;
}
           

继续阅读