01分数规划:
#include <iostream>
#include <stdio.h>#include <algorithm>
#include <cmath>
using namespace std;
struct node
{
long long id,v,w;
double t;
}a[100005];
long long n,m,maxx=10000000;
double eps=1e-6;
bool cmp(node a,node b)
{
return a.t>b.t;
}
bool did(double r)
{
double sum=0;
for (int i=1;i<=n;i++)
{
a[i].t=a[i].v-r*a[i].w;
}
sort(a+1,a+n+1,cmp);
for (int i=1;i<=m;i++) sum+=a[i].t;
return sum>0;
}
int main()
{ cin>>n>>m;
for (int i=1;i<=n;i++)
{
cin>>a[i].v>>a[i].w;
a[i].id=i;
}
double left=0,right=maxx,mid;
while (fabs(right-left)>eps)
{
mid=(left+right)/2;
if (did(mid)) left=mid;else right=mid;
}
for (int i=1;i<m;i++) cout<<a[i].id<<" ";cout<<a[m].id;
return 0;
}
/*
题意:给定n个结点,每个结点有v,w两个值,求含k个结点的子集,使得sum(v)/sum(w)最大。
题解:0,1分数规划,求g=sum(v)/sum(w)最大,二分枚举g的值,求sum(v-g*w)的最小值,即选出n个结点中v-g*w的最小的k个元素,加起来与0进行比较。
思路:二分
设最后选定物品的集合为S
用 sigma(i in S) V[i] 所有的价值和
用 sigma(i in S) W[i] 所有的质量和
ans = sigma(i in S) V[i] / sigma(i in S) W[i]
根据化简得到:
sigma(v[i] - ans*w[i] ) =0 (单调减) 那么我们就二分这个就行 */