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的主要内容,如果未能解决你的问题,请参考以下文章