nyoj914(二分搜索+贪心)

题目意思:

acm.nyist.net/JudgeOnline/problem.php?pid=914

如今有n个物品的重量和价值各自是Wi和Vi,你能帮他从中选出k个物品使得单位重量的价值最大吗?

输入
有多组測试数据
每组測试数据第一行有两个数n和k。接下来一行有n个数Wi和Vi。
(1<=k=n<=10000) (1<=Wi,Vi<=1000000)
输出
输出使得单位价值的最大值。(保留两位小数)
例子输入
3 2
2 2
5 3
2 1
例子输出
0.75
题目分析:

此题直接对单位价格进行贪心会出现故障,并且不难从例子上看出来。因为k个物品的单位价格一定不大于最大单位价格的物品,

并且一定会大于0,因此能够用二分搜素+贪心来解题。

详细细节见凝视


AC代码:

 
/**
 *贪心+二分搜索
 */
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define exp 1e-5
using namespace std;
typedef struct node{
    double w,v;
}node;
node p[10005];
double y[10005];
int n,k;
int cmp(double a,double b){
    if(a>b) return 1;
    return 0;
}
int Judge(double x){//二分搜索最大的且最恰当的值是否合理。if(合理)证明还有继续加大的空间,能够继续增大
    for(int i=0;i<n;i++){
        y[i]=p[i].v-p[i].w*x;
    }
    sort(y,y+n,cmp);
    double s=0;
    for(int i=0;i<k;i++){
        s+=y[i];
    }
    if(s>=0) return 1;
    else return 0;
}
double Search(double ma){
    double l=0,r=ma;
    while(r-l>exp){
        double mid=(l+r)/2;
        if(Judge(mid)){//当前值还小,还要增大
            l=mid;
        }
        else{//当前值大了,须要减小
            r=mid;
        }
    }
    return l;//或者return r;此时l=r
}
int main()
{
    while(scanf("%d%d",&n,&k)!=EOF){
        double ma=0;//k个最大平均值一定小于等于单个最大价值且大于0
        for(int i=0;i<n;i++){
            scanf("%lf%lf",&p[i].w,&p[i].v);
            if(ma<p[i].v/p[i].w) ma=p[i].v/p[i].w;
        }
        printf("%.2lf ",Search(ma));
    }
    return 0;
}
       

原文地址:https://www.cnblogs.com/brucemengbm/p/6922503.html