POJ 3111 K Best 二分(最小化平均值)

来源:互联网 发布:康佳电视的网络功能 编辑:程序博客网 时间:2024/06/10 22:44

题目:

http://poj.org/problem?id=3111

题意:

给定n个物品,每个物品有价值和重量,现在从其中选出k个物品,使这些物品的单位价值最大,并输入一组选择方案(任一组)

思路:

一般思路是对物品按单位价值排序取前k个,然而这样是不对的,可以找到反例。单位重量的价值为sum(v[i]) / sum(w[i]),于是枚举单位重量价值x,就变成了sum(v[i]) / sum(w[i]) >= x,sum(v[i] - x * w[i]) >= 0,找到满足上述不等式的最大x值(来自挑战程序设计竞赛)

#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>#include <vector>#include <cmath>#include <queue>using namespace std;const int N = 100010, INF = 0x3f3f3f3f;struct node{    double val;    int idx;    friend bool operator< (node a, node b)    {        return a.val > b.val;    }} arr[N];int n, k;int w[N], v[N], res[N];bool work(double mid){    for(int i = 1; i <= n; i++)        arr[i].idx = i, arr[i].val = v[i] - mid * w[i];    sort(arr + 1, arr + 1 + n);    double sum = 0;    for(int i = 1; i <= k; i++) sum += arr[i].val, res[i] = arr[i].idx;    return sum >= 0;}int main(){    while(~ scanf("%d%d", &n, &k))    {        for(int i = 1; i <= n; i++) scanf("%d%d", &v[i], &w[i]);        double l = 0.0, r = INF;        //for(int i = 1; i <= 100; i++)//用这个会超时        while(r - l > 1e-6)        {            double mid = (l + r) / 2;            if(work(mid)) l = mid;            else r = mid;        }        for(int i = 1; i <= k; i++) printf("%d%c", res[i], i == k ? '\n' : ' ');    }    return 0;}
0 0
原创粉丝点击