jzoj4230-淬炼神体【0/1分数规划】

版权声明:原创,未经作者允许禁止转载 https://blog.csdn.net/Mr_wuyongcong/article/details/86561780

正题


题目大意

n n 个东西,有 a i , b i a_i,b_i 。选择 k k 个,使得 a i / b i \sum a_i/\sum b_i 最大。


解题思路

a i / b i = k \sum a_i/\sum b_i=k
a i / b i / k = 1 \sum a_i/\sum b_i/k=1
a i / k = b i \sum a_i/k=\sum b_i
那么
( a i / k b i ) > = 0 \sum (a_i/k-b_i)>=0
然后二分 k k 就好了
然后每次选取 a i / k b i a_i/k-b_i 最大的 k k 个就好了


c o d e code

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=100010;
int n,k;
double l,r,a[N],b[N],c[N];
bool check(double ks)
{
	double ans=0;
	for(int i=1;i<=n;i++){
		c[i]=a[i]/ks-b[i];
	}
	sort(c+1,c+1+n);
	for(int i=n;i>=n-k+1;i--)
	  ans+=c[i];
	return (ans>=0);
}
int main()
{
	//freopen("data.in","r",stdin);
	//freopen("data.out","w",stdout);
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++)
	  scanf("%lf",&a[i]);
	for(int j=1;j<=n;j++)
	  scanf("%lf",&b[j]);
	l=1e-4;r=20000;
	while(r-l>1e-6){
		double mid=(l+r)/2;
		if(check(mid)) l=mid;
		else r=mid;
	}
	printf("%0.3lf",l);
}

猜你喜欢

转载自blog.csdn.net/Mr_wuyongcong/article/details/86561780