[01分数规划]POJ2976 Dropping tests]经典二分题-01分数规划

30 篇文章 0 订阅
1 篇文章 0 订阅

题目链接

题目描述

给定N个元素,每个元素含有A[i],B[i],取其中N-K个元素得到:\frac{\sum a_i}{\sum b_i}\cdot 100,最大化这个值.

分析

使用二分答案:二分一个值V,使得\frac{\sum a_i}{\sum b_i} >= v,化简:\frac{\sum a_i}{\sum b_i} >= v \Rightarrow \sum a_i >= v\cdot \sum b_i \Rightarrow \sum a_i - v\cdot \sum b_i >= 0\Rightarrow \sum (a_i - v\cdot b_i) >= 0

那么可以在二分的check函数中选择前N-K个最大的(a_i - v\cdot b_i),检查是否大于等于0.

注意精度的处理。

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

const int MAXN = 1001;

int N,K;
double
 A[MAXN],B[MAXN];

bool cmp(double a,double b)
{
	return a > b;
}

bool Check(double x)
{
	double Ssd[MAXN];
	for(int i = 1;i <= N;i++)
	{
		Ssd[i] = A[i]-x*B[i];
	}
	
	sort(Ssd+1,Ssd+1+N,cmp);
	
	double res = 0;
	for(int i = 1;i <= K;i++)
	{
		res += Ssd[i];
	}
	
	if(res >= 0)
	{
		return true;
	}
	else
	{
		return false;
	}
}

int main(void)
{
	cin >> N >> K;
        //K 是可能等于0的
	while(N != 0 || K != 0)
	{
		double l = 0;
		double r = 1;
		
		K = N-K;
		for(int i = 1;i <= N;i++)
		{
			cin >> A[i];
		}
		
		for(int i = 1;i <= N;i++)
		{
			cin >> B[i];
			
			r = max(r,A[i]/B[i]);
		}
		
		double ans = 0;
		while(r-l >= 1e-6)
		{
			double mid = (l+r)/2;
			
			if(Check(mid))
			{
				ans = mid;
				l = mid;
			}
			else
			{
				r = mid;
			}
			
		}
		printf("%.0lf\n",ans*100);
		cin >> N >> K;
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值