01分数规划

01分数规划,即给定模型求sum(ai)/sum(bi)的最值;

我们可以改变一下式子的形态:

sum(ai)/sum(bi)>=L

=sum(ai)-L*sum(bi)>=0

所以我们可以通过二分判断L的取值;

 

标准的二分代码:

 

#include<cstdio>
#include<algorithm>
#include<ctype.h>
#include<string.h>
#include<math.h>

using namespace std;
#define ll long long

inline char read() {
    static const int IN_LEN = 1000000;
    static char buf[IN_LEN], *s, *t;
    return (s==t?t=(s=buf)+fread(buf,1,IN_LEN,stdin),(s==t?-1:*s++):*s++);
}
template<class T>
inline void read(T &x) {
    static bool iosig;
    static char c;
    for (iosig=false, c=read(); !isdigit(c); c=read()) {
        if (c == '-') iosig=true;
        if (c == -1) return;
    }
    for (x=0; isdigit(c); c=read()) x=((x+(x<<2))<<1)+(c^'0');
    if (iosig) x=-x;
}

const int N = 100005;
int n, k, a[N], b[N], g[N];
double f[N];
inline bool cmp(int x, int y){ return f[x]>f[y];}
inline double check(double x){
    for(int i=1; i<=n; ++i) f[i]=a[i]-b[i]*x, g[i]=i;
    nth_element(g+1, g+k+1, g+n+1, cmp);
    ll sa=0, sb=0;
    for(int i=1; i<=k; ++i) sa+=a[g[i]], sb+=b[g[i]];
    return (double)sa/sb;
}
int main() {
    read(n), read(k);
    for(int i=1; i<=n; ++i) read(a[i]);
    for(int i=1; i<=n; ++i) read(b[i]);
    double l=0, r=1e6, ans=0;
    while(r-l>1e-7){
        double mid=(l+r)/2;
        if(check(mid)>=mid) ans=mid, l=mid; else r=mid;
    }
    return printf("%.4f", ans), 0;
}

 

posted @ 2019-09-09 19:22  神之右大臣  阅读(344)  评论(0编辑  收藏  举报