AtCoder Beginners Contest 034 D - 食塩水
問題概要
濃度と重量がわかっている 個の食塩水から個を選んで混ぜる時, 最大の濃度を求めよ。
考えたこと
二分探索を用いて最大濃度を計算するのはすぐわかったが, 以下のコードでのcheck関数をどう実装するか(どのようにその濃度の食塩水を作れるか否か判定するか)分からなかった。
lower = 0 upper = 100 while upper - lower > 10 ** (-5): half = (upper+lower) / 2 if check(half): lower = half else: upper = half print(lower)
色々実験したところ, 以下の結論に達した。そもそも, 濃度の食塩水が作れるとはどういうことか? 濃度がより大きい個の食塩水が集められれば, 確実に条件を達成できる。では, 個集められないときは? 濃度の食塩水と, 濃度の食塩水を混ぜるときのことを考えてみよう。それぞれの重さを, として,
$$ p_1 \times w_1 + p_2 \times w_2 - P * (w_1 + w_2) = \\ (p_1 - P) \times w_1 + (p_2 - P) \times w_2 \geq 0 $$
が成立すれば, このつの食塩水を混ぜることで, 濃度以上の食塩水を作ることができる。これを一般化することで, check関数が実装できる。 優先的に使う食塩水は, について, 降順に並べることで得られる。
解答
自分が書いたコードは以下
N, K = map(int, input().split()) WP = sorted([list(map(int, input().split())) for i in range(N)], key=lambda x: x[1], reverse=True) def check(half): cur = 0 salt = sorted(WP, key=lambda x: x[0]*(x[1]-half), reverse=True) for i in range(K): cur += salt[i][0] * (salt[i][1]-half) if cur >= 0: return True return False lower = 0 upper = 100 while upper - lower > 10 ** (-5): half = (upper+lower) / 2 if check(half): lower = half else: upper = half print(lower)