最大化平均值问题

最大化平均值问题

题意

n个物品,有体积和价值里拿k个,问怎么样拿,k个物品的平均价值(总价值/总体积)最大。

笺释

如果按照价值/体积排序,贪心选取之后并不能保证最后的总平均价值最大。
转化为不等式就是

a+w1/b+v1>a+w2/b+v2

w1/v1>w2/v2 并不能保证上述不等式成立。
这让我想起了西电第一周e题,那个题之所以能拿就拿是因为最终要最优化的是全部价值之和,就等于是用密度不同的物质去填满一定体积的球,那肯定是能用密度大的就用密度大的了。
而这道题的话,我们二分价值,只需要确定n个物品里选k个能否达到这个平均价值即可,如果能,平均价值变大,否则变小。
而在确定了价值x的基础上可以对n个物品进行排序。

因为最终要确定的是sum(v)/sum(w)>=x,也就是sumv>=sum(w)*x,对于求和来说,可以将x放入求和号内,最终确定只要v-w*x大的就一定选。按照v-w*x排序后。选前k个就好了。

完整代码

#include<bits/stdc++.h>
#define MAXN 1005
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
int n,k;
double x;
struct node
{
    double w,v;
}nodes[MAXN];
bool cmp(node n1,node n2)
{
    return n1.v-n1.w*x>n2.v-n2.w*x;
}
int check()
{
    sort(nodes+1,nodes+1+n,cmp);
    double ans1=0,ans2=0;
    for(int i=1;i<=k;i++)
    {
        ans1+=nodes[i].v;
        ans2+=nodes[i].w;
     //   printf("B %f %f\n",nodes[i].v,nodes[i].w);
    }
   // printf("%f %f\n",ans1,ans2);
    if(ans1/ans2>=x)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}
int main()
{
    scanf("%d %d",&n,&k);
    double l=INF;
    double r=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%lf %lf",&nodes[i].w,&nodes[i].v);
       // printf("C %f %f\n",nodes[i].v,nodes[i].w);
        l=min(l,nodes[i].v/nodes[i].w);
        r=max(r,nodes[i].v/nodes[i].w);
    }
    int flag=0;
    while(l<=r)
    {
        flag++;
        if(flag>100)
        {
            break;
        }
        x=(l+r)/2;
        if(check())
        {
            l=x;
        }
        else
        {
            r=x;
        }
    }
    printf("%f\n",l);
}

猜你喜欢

转载自www.cnblogs.com/SoniciSika/p/9030815.html