题目描述:
有n个物品的重量和价值分别为Wi和Vi。从中选出k个物品使得单位重量的价值最大。
例如:
n=3
k=2
(w,v)={(2,2) , (5,3) , (2,1) }
输出应为0.75
分析:
一般我们最先想到的就是把物品按照单位价值进行排序,从大到小贪心的进行选取。但是这种方法对于样例的输出应该为5/7=0.714,所以这个方法是不行的。
这个问题应该使用二分搜索法解决,定义:
C(x),表示,可以选择的单位重量的价值不小于x
我们要求满足C(x)的最大的x,
单位重量的价值为:Vi / Wi
Vi / Wi>=x.
即C(x)=(Vi -x Wi),从大到小排序中的钱k个的和不小于0.
代码:
#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
int n,k;
int w[10009],v[10009];
double y[10009];
bool cmp(double a,double b)
{
return a>b;
}
bool C(double x)
{
for(int i=0;i<n;i++)
y[i]=v[i]-x*w[i];
sort(y,y+n,cmp);
double sum=0;
for(int i=0;i<k;i++)
sum+=y[i];
return sum>=0;
}
void solve()
{
double lb=0,ub=0x3f3f3f3f;
for(int i=0;i<100;i++)
{
double mid=(lb+ub)/2;
if(C(mid)) lb=mid;
else
ub=mid;
}
printf("%.2lf
",ub);
}
int main()
{
scanf("%d%d",&n,&k);
for(int i=0;i<n;i++)
scanf("%d%d",&w[i],&v[i]);
solve();
return 0;
}