题目:《挑战程序设计》P143
有 n 个物品的重量和价值分别是 wi 和 vi 。从中选出 k 个物品使得单位重量的价值最大
1<=k<=n<=10^4
1<=w[i],v[i]<=10^6
思路:二分
设最后选定物品的集合为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 那么我们就二分这个就行
Input :
3 2
2 2
5 3
2 1
Output:
0.75
#include <cstring>
#include <cmath>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <set>
#include <cstdio>
#include <vector>
#include <queue>
#include <map>
using namespace std;
#define maxn 10010
double w[maxn],v[maxn],c[maxn];
int n,k;
bool ok(double ans)
{
for(int i=0;i<n;i++)
c[i]=v[i]-ans*w[i];
sort(c,c+n);
double cnt=0;
for(int i=0;i<k;i++)
cnt+=c[n-1-i];
return cnt>=0;
}
int main()
{
scanf("%d%d",&n,&k);
for(int i=0;i<n;i++)
scanf("%lf%lf",&w[i],&v[i]);
double l=0,r=1000010;
while(abs(l-r)>1e-6)
{
double mid=(l+r)/2;
if(ok(mid))
l=mid;
else
r=mid;
}
printf("%.2lf\n",r);
return 0;
}