zoukankan      html  css  js  c++  java
  • [POJ2976]Dropping tests

    [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_iin[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
    ",(int)(l*100+0.5));
    	}
    	return 0;
    }
    
  • 相关阅读:
    小点
    三.一些常用类
    字符串相关:String,StringBuffer,StringBuilder
    五.二叉树
    四.递归
    三.队列
    二.栈
    一.数组,链表
    RDLC 矩阵图片列表排列顺序乱
    RDLC 矩阵每隔一页就有空白页 矩阵 空白页
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/9060678.html
Copyright © 2011-2022 走看看