AT274の技術だったりなかったり

あっとのTECH LOG

競プロのこととか技術のこととか。たまに日常を書きます。

ABC144 D - Water Bottle

問題原文

atcoder.jp

問題要旨

底面が一辺  A cm の正方形であり、高さが  B cm であるような直方体に、  X cm^{3} の水が入っている。
この直方体を底面の一辺を軸として傾けたとき、水が溢れ出す時の角度を求めよ。

  •   1 \leq A, B \leq 100
  •   1 \leq X \leq a^{2}b

解法

解説放送を丸パクリします()

立体の問題 → 平面の問題に

立体のままでは考えにくいので、 平面として考えられるようにする。
具体的には、  X / A をやれば、正面から見た時に水がどれぐらいの高さまで入っているかという情報に変換できる。 これを以後  S とする。

f:id:AT274:20200129103510p:plain
問題の平面への変換

傾けたときの状態には二種類ある

まず、求めたい角度はここ。

f:id:AT274:20200129105732p:plain
求めたいところ

で、このままでは考えにくいので、「直方体は傾けずに中の水の量だけ傾けていく」とすると、ちょうど水が溢れる角度のパターンには2種類あることがわかる。

まずはパターン1。

f:id:AT274:20200129110315p:plain
パターン1

次にパターン2。

f:id:AT274:20200129110505p:plain
パターン2

「水の量が全体の半分以上かどうか」で場合わけが必要なことがわかる。

パターン1

f:id:AT274:20200129110755p:plain
パターン1解法

こんな感じにやれば、  h が求められる。
 h が求められれば  atan2(h, A) などで角度が求められる。

パターン2

f:id:AT274:20200129111022p:plain
パターン2解法

三角形の面積の公式から、  w が求められる。
 w が求められれば  atan2(B, w) などで角度が求められる。

実装

from math import atan2, degrees
A, B, X = map(int, input().split())
S = X / A


if S >= A * B / 2:
    h = (2 * (A * B - S)) / A
    print(degrees(atan2(h, A)))

else:
    w = (2 * S) / B
    print(degrees(atan2(B, w)))

感想

き ら い 笑 でも atan2 はよく使うらしいから覚えとこう。
当時Twitterはこの問題を作ったwriterさんを燃やす埋めるだのなんか盛り上がってたけど、いま振り返ると普通に良問に見える。 (atan2 の導入によさそう)

めちゃめちゃわかりやすい解説放送

すぬけさん大好き