01分数规划

01分数规划,就是这样一个东西
\(max(\frac{\sum ai * xi}{\sum bi * xi})\),其中\(xi \in {0,1}\)
简而言之,就是在n个物品中选出任意几个【或者可以有限制选多少个】,使得其两种权值a,b的比值最大

这样的问题可以二分解决
假如有这样一道裸题:POJ2976,选n - k个物品使得比值最大
我们二分出r,
若存在\(\frac{\sum ai * xi}{\sum bi * xi} >= r\),则r可行
变形得\(\sum ai * xi - r * \sum bi * xi >= 0\)
我们就可以把每件物品看做是权值\(ai - bi * r\),排个序看看前n - k大之和是否大于0即可

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
using namespace std;
const int maxn = 1005,maxm = 100005,INF = 1000000000;
int n,k;
double A[maxn],B[maxn],t[maxn];
bool check(double x){
	REP(i,n) t[i] = A[i] - x * B[i];
	sort(t + 1,t + 1 + n);
	double sum = 0;
	for (int i = k + 1; i <= n; i++) sum += t[i];
	return sum > 0;
}
int main(){
	while (~scanf("%d%d",&n,&k) && (n || k)){
		REP(i,n) scanf("%lf",&A[i]);
		REP(i,n) scanf("%lf",&B[i]);
		double l = 0,r = 1.0,mid;
		while (r - l > 0.0000001){
			mid = (l + r) / 2;
			if (check(mid)) l = mid;
			else r = mid;
		}
		printf("%d\n",(int)round(l * 100));
	}
	return 0;
}

posted @ 2018-02-15 13:43  Mychael  阅读(362)  评论(0编辑  收藏  举报