AtCoder Beginner Contest 144「D - Water Bottle」(Ruby)

図を描いて三角関数を使えば、実装は比較的簡単 (図をキレイに書くスキルが欲しい・・・)

問題

問題文 高橋君は、底面が 1 辺 a

c m の正方形であり、高さが b

c m であるような直方体型の水筒を持っています。(水筒の厚みは無視できます。)

この水筒の中に体積 x

c m 3 の水を入れ、底面の正方形の 1 辺を軸として、この水筒を徐々に傾けます。

水を溢れさせずに水筒を傾けることができる最大の角度を求めてください。

制約 入力は全て整数 1 ≤ a ≤ 100 1 ≤ b ≤ 100 1 ≤ x ≤ a 2 b

atcoder.jp

考えたこと

こういった図形絡みの問題は、実際に図を描いた方が分かりやすいと思ったので、図を描いてみました。

f:id:ryoutaku_jo:20191027235758j:plain

水の体積と底面の正方形の 1 辺の長さから、水面までの高さを割り出せます。

底面の正方形の 1 辺を軸として水筒を徐々に傾けるので、傾きを考える時は面で考えて良さそう。

傾きを考える時、二つのパターンがありそう。

一つは、最大まで傾けても、水面が底面に達しない場合。

これはコップを傾けたことで水に接している左辺の長さが伸びると、右辺はそれに反比例して縮むことに着目して、各辺の長さを割り出しています。

f:id:ryoutaku_jo:20191027235811j:plain

もう一つは、最大まで傾けてると、水面が底面に達する場合。

これはコップを傾けて水が接している面の形が変わっても、面積は変わらないことに着目して各辺の長さを割り出しています。

f:id:ryoutaku_jo:20191028023141j:plain

それぞれ計算方法が異なるので、条件分岐が必要。

この二つのパターンを三角関数の公式に当てはめれば良さそう。

detail.chiebukuro.yahoo.co.jp

docs.ruby-lang.org

コード

a,b,x = gets.split(' ').map(&:to_i)
 
if b-2*x.to_f/(a*a) <= 0
  puts Math.atan2((b-x.to_f/(a*a))*2, a) * 180 / Math::PI
else
  puts Math.atan2(b, 2*x.to_f/(a*b)) * 180 / Math::PI
end

コード長 244 Byte
実行時間 7 ms
メモリ 1788 KB