01分数规划——POJ3111

Posted helman

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了01分数规划——POJ3111相关的知识,希望对你有一定的参考价值。

题目链接

题目含义

寻找k个钻石,使得sigmaVi/sigmaWi最大,然后输出这些钻石的序号

题目分析

若使sigmaVi/sigmaWi取得最大值,那么取任意k个钻石的答案ans

ans<=sigmaVi/sigmaWi

转换一下就是  sigmaVi-sigmaWi*ans>=0

再转换一下就是  sigma(  Vi-Wi*ans  )>=0

ans用二分来找,如果满足上面的式子low=mid

否则high=mid

至于输出序号,我用的结构体和vector存储每次二分的序号

题目代码

注意二分上界开大一点

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=1e5+7;
const double eps=1e-7;
struct Node
    int id;
    double v,w,val;
node[maxn];
bool cmp(Node a,Node b)
    return a.val>b.val;

int n,k;
double r,l,mid,sum;
vector<int>v;
int main()
    scanf("%d%d",&n,&k);
    l=0.0;r=3000;
    for(int i=1;i<=n;i++)
        scanf("%lf%lf",&node[i].v,&node[i].w);
        node[i].id=i;
        r=max(r,node[i].v/node[i].w);
    
    while(r-l>eps)
        mid=(l+r)/2;
        for(int i=1;i<=n;i++)
            node[i].val=node[i].v-node[i].w*mid;
        sum=0;
        v.clear();
        sort(node+1,node+1+n,cmp);
        for(int i=1;i<=k;i++)
            sum+=node[i].val;
            v.push_back(node[i].id);
        
        if(sum>=0)l=mid;
        else r=mid;
    
//    sort(v.begin(),v.end());
    for(int i=0;i<v.size();i++)
        if(!i)printf("%d",v[i]);
        else printf(" %d",v[i]);
    
    printf("\n");
    return 0;

 

以上是关于01分数规划——POJ3111的主要内容,如果未能解决你的问题,请参考以下文章

[POJ3111]K Best(分数规划, 二分)

poj 2976 基础01分数规划

01分数规划学习笔记

$POJ$2728 $Desert King$ 01分数规划

POJ2728Desert King - 01分数规划

poj2728 Desert King——01分数规划