2018年东北农业大学春季校赛 I wyh的物品【二分】

链接:https://www.nowcoder.com/acm/contest/93/I
来源:牛客网

题目描述

wyh学长现在手里有n个物品,这n个物品的重量和价值都告诉你,然后现在让你从中选取k个,问你在所有可能选取的方案中,最大的单位价值为多少(单位价值为选取的k个物品的总价值和总重量的比值)

输入描述:

输入第一行一个整数T(1<=T<=10)
接下来有T组测试数据,对于每组测试数据,第一行输入两个数n和k(1<=k<=n<=100000)
接下来有n行,每行两个是a和b,代表这个物品的重量和价值

输出描述:

对于每组测试数据,输出对应答案,结果保留两位小数
示例1

输入

1
3 2
2 2
5 3
2 1

输出

0.75

说明

对于样例来说,我们选择第一个物品和第三个物品,达到最优目的

做法:
二分,对于每一个答案C,有 s[i] = w[i]-c*v[i]
排序,取最大前k个,如果大于等于0则可行,否则不可行

代码:
#include<iostream>
using namespace std;
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
struct Thing{
    double w,v;
    double dj;
    double s;
    void count(double c){
        s = w-c*v;
    }
    bool operator<(const Thing &pt)const{
        return s>pt.s;
    }
};
int n,m;
Thing thing[110000];
int check(double c){
    for(int i=0;i<n;i++){
        thing[i].count(c);
    }
    sort(thing,thing+n);
    double sum = 0;
    for(int i=0;i<m;i++)
        sum+=thing[i].s;
    if(sum>0)
        return 1;
    else
        return 0;    
}
void deal(){
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++){
        scanf("%lf%lf",&thing[i].v,&thing[i].w);
        thing[i].dj = thing[i].w/thing[i].v;
    }
    double l = 0, r = 1e9;
    while(l<=r){
        double mid = (l+r)/2;
        int ans = check(mid);
        if(ans==1)
            l=mid+0.0001;
        else
            r=mid-0.0001;
    }
    printf("%.2f\n",r);
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--)
        deal();    
    return 0;
}

 

posted @ 2018-04-06 11:06  晓风微微  阅读(172)  评论(0编辑  收藏  举报