とても典型的な「平均値の最大化」→「二分探索」の問題!
問題概要
個の食塩水がある。
番目の食塩水は、重さが
グラムであり、濃度
パーセントである。
これらの食塩水から 個選んで混ぜてできる食塩水の濃度の最大値を求めよ。
制約
考えたこと
ザ・「平均値の最大化」問題である。この手の問題は二分探索が効く!
混ぜてできる食塩水の濃度を パーセント以上にできるかどうかを判定する問題を解こう。
さて、混ぜる 個の各食塩水について、溶けている食塩の重さを
として、食塩水の重さを
としたとき、混ぜた食塩水が
パーセント以上である条件を考察すると、
⇔
となる。よって、 の総和によって判定できることがわかった。判定問題は次のようにして解決できる。
個の食塩水のうち、
の値が大きい順に 個とった総和が 0 以上であるかを判定する
計算量は、二分探索のイテレーション回数を として、
となる。
コード
#include <bits/stdc++.h> using namespace std; int main() { int N, K; cin >> N >> K; vector<double> w(N), p(N); for (int i = 0; i < N; ++i) cin >> w[i] >> p[i]; double lo = 0.0, hi = 100.0; for (int i = 0; i < 50; ++i) { double mi = (lo + hi) / 2; vector<double> tmp(N); for (int j = 0; j < N; ++j) { tmp[j] = (p[j] - mi) * w[j]; } sort(tmp.begin(), tmp.end(), greater<double>()); double sum = 0.0; for (int j = 0; j < K; ++j) sum += tmp[j]; if (sum < 0.0) hi = mi; else lo = mi; } cout << fixed << setprecision(9) << hi << endl; }