码迷,mamicode.com
首页 > 其他好文 > 详细

[POJ2976]Dropping tests

时间:2018-05-19 18:35:44      阅读:138      评论:0      收藏:0      [点我收藏+]

标签:||   ref   code   算法   while   sdn   ons   eps   using   

[POJ2976]Dropping tests

vjudge

题意

给你\(\{a_1,a_2...a_n\}\)\(\{b_1,b_2...b_n\}\),构造\(\{c_1,c_2...c_k\}\),其中\(c_1<c_2<...<c_k\)\(c_i\in[1,n]\),最大化\(L=\frac{\sum_{i=1}^{k}a_{c_i}}{\sum_{i=1}^{k} b_{c_i}}\)

sol

分数规划。
二分一个答案\(mid\)。令\(d_i=a_i-mid*b_i\),接着检查是否可以选出\(k\)\(d_i\)使其总和大于\(0\)。若满足条件,稍微推一下式子就可以得到,存在一个更优于\(mid\)的解,于是令\(l=mid\)。若不满足则令\(r=mid\)
其实有一个优于二分的做法,叫做\(Dinkelbach\)。复杂度上可能会比二分优秀一些,但算法本身需要根据当前答案计算一个新的答案从而不断逼近最终答案,而计算一个答案和二分中判断一个答案的写法是存在一定差异的。
对于\(Dinkelbach\)算法在此不多介绍,安利一篇博客戳我

code

#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int gi()
{
    int x=0,w=1;char ch=getchar();
    while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    if (ch=='-') w=0,ch=getchar();
    while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return w?x:-x;
}
const int N = 1e3+5;
const double eps = 1e-4;
int n,k,a[N],b[N];double d[N];
int main()
{
    while (233){
        n=gi();k=gi();
        if (n+k==0) break;
        for (int i=1;i<=n;++i) a[i]=gi();
        for (int i=1;i<=n;++i) b[i]=gi();
        double l=0,r=1;
        while (r-l>eps){
            double mid=(l+r)/2,tmp=0;
            for (int i=1;i<=n;++i) d[i]=(double)a[i]-mid*b[i];
            sort(d+1,d+n+1);
            for (int i=n;i>k;--i) tmp+=d[i];
            if (tmp>eps) l=mid;else r=mid;
        }
        printf("%d\n",(int)(l*100+0.5));
    }
    return 0;
}

[POJ2976]Dropping tests

标签:||   ref   code   算法   while   sdn   ons   eps   using   

原文地址:https://www.cnblogs.com/zhoushuyu/p/9060678.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!