题意:
有n个物品的重量和价值分别是wi和vi。从中选出k个物品使得单位重量的价值最大
输入:
3 2
2 2
5 3
2 1
输出:
0.75
分析:
一般最先想到的方法可能是把物品按照单位价值进行排序,从小到大贪心的进行选取,但是这个方法对于样例输入得到的结果是5/7=0.714.所以这个方法是不可行的。实际上,对于这个问题使用二分搜索法可以很好的解决。我们定义
条件C(x):=可以选择使得单位重量的价值不小于x
因此原问题就变成了求满足C(x)的最大的x。
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 10000 + 10;
const int INF = 100000000;
int n, k;
int w[maxn], v[maxn];
double y[maxn]; // v - x * w
//判断是否满足条件
bool C(double x)
{
for (int i = 0; i < n; i++){
y[i] = v[i] - x * w[i];
}
sort(y, y + n);
//计算y数组中从大到小前k个数的和
double sum = 0;
for (int i = 0; i < k; i++){
sum += y[n - i - 1];
}
return sum >= 0;
}
void solve()
{
double lb = 0, ub = INF;
for (int i = 0; i < 100; i++){
double mid = (lb + ub) / 2;
if (C(mid))
lb = mid;
else
ub = mid;
}
printf("%.2lf\n", 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;
}