码迷,mamicode.com
首页 > 其他好文 > 详细

nyoj914(二分搜索+贪心)

时间:2014-11-02 21:03:42      阅读:117      评论:0      收藏:0      [点我收藏+]

标签:nyoj   贪心   二分搜索   

题目意思:

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\n",Search(ma));
    }
    return 0;
}
       

nyoj914(二分搜索+贪心)

标签:nyoj   贪心   二分搜索   

原文地址:http://blog.csdn.net/fool_ran/article/details/40714147

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!