题意:
有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 ", 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; }