欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

二分搜索,最大化平均值 Poj-3111

程序员文章站 2022-05-13 19:57:51
...

题目链接:https://vjudge.net/problem/POJ-3111

题目大意就是给你一堆有价值和重量的珠宝,问你如何挑选能够是最终单位珠宝的价值最大。

 

首先我们的思路肯定是贪心,按照它们的单位价值进行排序,取最大的几个。但是这是错误的。在这组数据中贪心就是错误的

k = 2

{w,v} = {2,2} , {5,3} , {2,1}

依照贪心的思想我们肯定会选取 {5,3}和{2,2}这一组,此时的单位价值x = 7/3 = 0.714,但实际情况我们取到了{2,2} + {2,1}

x  = 0.75。故此可以得出贪心的思路是错误的。于是去枚举珠宝单价的可能性,常规的暴力会TLE,于是我们是用二分的思想去枚举将时间复杂度从O(n) 降为log(n)。

 

讲解来自《挑战程序设计竞赛》

设最大的单位价值为x。那么让x成立的条件为 ∑v / ∑w ≥ x 化简可以得到 ∑v / ∑w ≥ x  = > ∑v ≥ x * ∑w = ∑ (x*w)  = > ∑ (v - x * w) ≥  0所以我们只要让前k个物品都满足这个条件,那么此时的x就是符合条件的,我们再去找更大的就可以了。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
#define lson l m rt << 1
#define rson m+1 r rt << 1|1
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int INF = 0x3f3f3f3f;
const int maxn = 1e6+10;
const int mod = 1000;
ll v[maxn],w[maxn];
ll T,n,k;
inline void fast()
{
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
}

struct Node
{
    int v,w,id; //价值,重量,编号
    double y;//排序时候判断是否都满足x
}a[maxn];

bool cmp(Node a,Node b)  //从大到小排序
{
    return a.y > b.y;
}

bool check(double x)
{
    for(int i = 0;i < n;++i)
    {
        a[i].y = a[i].v - a[i].w*x;   //推导出来的公式
    }

    sort(a,a+n,cmp);

    double sum = 0;
    for(int i = 0;i < k;++i)  //如果sum最后大于零表示此时的X合适我们去二分更大的
        sum += a[i].y;

    return sum >= 0;
}

int main()
{
    fast();
    while(scanf("%lld %lld",&n,&k) != EOF)
    {
        for(int i = 0;i < n;++i)
        {
            scanf("%d %d",&a[i].v,&a[i].w);
            a[i].id = i+1;
        }

        double l = 0,r = INF;
        for(int i = 0;i < 100;++i)
        {
            double mid = (l + r)/2;
            if(check(mid))
                l = mid;
            else
                r = mid;
        }

        for(int i = 0;i < k;++i)
        {
            if(i == 0)
                printf("%d",a[i].id);
            else
                printf(" %d",a[i].id);
        }
        printf("\n");
    }
	return 0;
}

 

相关标签: 二分搜索