POJ 2976 Dropping tests

来源:互联网 发布:windows nt4.0下载 编辑:程序博客网 时间:2024/06/11 08:06

大意不再赘述。

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;}