POJ 2976 Dropping tests

大意不再赘述。

0/1分数规划,关键在于了解二分枚举时得到的ans值不是最终值,自身枚举的mid值才是。了解通过函数的单调性,凹性,构造出Q(L) = cx - L* x dx 得到原问题的子问题,然后通过二分枚举或者其他的方法求得解。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using namespace std;

const int MAXN = 1010;
const double eps = 1e-4;

struct node
{
	double x, y;
}a[MAXN];

int n, k;

int read_case()
{
	scanf("%d%d", &n, &k);
	if(!n && !k) return 0;
	for(int i = 0; i < n; i++) scanf("%lf", &a[i].x);
	for(int i = 0; i < n; i++) scanf("%lf", &a[i].y);
	return 1;
}

double build(double mid)
{
	double t[MAXN] = {0};
	double ans = 0;
	for(int i = 0; i < n; i++)
	{
		t[i] = a[i].x - mid*a[i].y;
	}
	sort(t, t+n, greater<double> ()); //用了sort之后,如果是从1开始输入的,那么排序之后下标变为0。 
	for(int i = 0; i < n-k; i++)
	{
		ans += t[i];
	}
	return ans;
}

void solve()
{
	double x = 0, y = 1.0;
	while(y-x > eps)
	{
		double mid = x+(y-x)/2;
		if(build(mid) > 0) x = mid;
		else y = mid;
	}
	printf("%.f\n", x*100);
}

int main()
{
	while(read_case())
	{
		solve();
	}
	return 0;
}


你可能感兴趣的:(POJ 2976 Dropping tests)