最大化平均值

基本问题:

有 n 个物品的重量和价值分别为 $w_i$ 和 $v_i$, 从中选 k 个物品使得单位重量的价值最大,即:

 这个式子值最大。


POJ2976

题意:

n 场测试, 每场一个 $a_i$ 和 $b_i$,要求去掉 k 门课,使得下面的式子最大:

 解法:

二分答案。

定义条件 C(x)= 可以选择使得单位重量的价值不小于x。

因此原问题就变成了求C(x)最大的x。假设选了某个集合S,则有:

$sum_{i - S}^{}V_i/sum_{i-S}^{}W_i$

这就变成了是否存在S满足下面的条件:
$sum_{i - S}^{}V_i/sum_{i-S}^{}W_i ge x$:

化简得:

$sum_{i-S}^{}(V_i-xW_i)ge0$

对式子左边得东西进行排序,贪心的进行选取,就变成了:

C(x)=$(V_i-xW_i)$从大到小排列中的前k个的和不小于0.

注意二分的时候ub和lb必须都是double,因为涉及到了除法

代码如下:

 1 int N, K;
 2 int a[MAXN], b[MAXN];
 3 double y[MAXN];
 4 
 5 bool C(double x) {
 6     int t = N - K;
 7     for (int i = 0; i < N; i++) y[i] = a[i] - x * b[i];
 8     sort(y, y + N);
 9     double sum = 0.0;
10     for (int i = 0; i < t; i++) sum += y[N - i - 1];
11     return sum >= 0.0;
12 }
13 
14 void solve() {
15     double ub = INF - 1, lb = 0;
16     while (ub - lb > EPS) {
17         double mid = (ub + lb)/2;
18         if (C(mid)) {
19             //cout << "true: " << mid << endl;
20             lb = mid;
21         }
22         else {
23             //cout << "false: " << mid << endl;
24             ub = mid;
25         }
26     }
27     cout << round(100 * lb) << endl;
28     return;
29 }
30 
31 int main() {
32 #ifndef ONLINE_JUDGE
33     FILE *stream1;
34     freopen_s(&stream1, "input.txt", "r", stdin);
35 #endif  // !ONLINE_JUDGE
36     while (cin >> N >> K) {
37         if (N == 0 && K == 0) break;
38         for (int i = 0; i < N; i++) cin >> a[i];
39         for (int i = 0; i < N; i++) cin >> b[i];
40         solve();
41     }
42     return 0;
43 }
原文地址:https://www.cnblogs.com/romaLzhih/p/12337209.html