ABC144D Water Bottle 解説
問題概要
底面が\(1\)辺\(a\ cm\)の正方形で、高さが\(b\ cm\)であるような直方体の容器に体積\(x\ cm^{3}\)の水を入れたのち傾けていく時、水が溢れる限界の角度を求める。
制約
- \(1\ \leq a,\ b \leq 100 \)
- \(1 \leq x \leq a^{2}b\)
考察
この問題のポイントとなるのは、水量が変化しないと言うことです。
1. 直方体 → 長方形へと変換
立体を傾けていく水の動きをシミュレーションするのは難しいので、底面が正方形であることから、水の体積を\(a\)で割ることで\(a\ \times \ b\)の長方形とする。
2. 入っている水の量によって場合分け
2-1. 入っている水のかさが半分以上の時
傾けていくと次のような状態で限界点を迎えます。
限界点では、図の通り、台形になっていることから台形の面積の公式により、水量を求め、図中の\(y\)を逆算します。
求める\(\theta\)は、 $$\theta = \tan^{-1} (\frac{b-y}{a})$$ となります。
2-2. 入っている水のかさが半分以下の時
限界点では、先ほどとは異なり、三角形の形状になります。先ほどと同様に、水量が変化しないことから図中の\(y\)を逆算すると、
図より、求める\(\theta\)は、 $$\theta = \tan^{-1}(\frac{b}{y})$$ となります。
実際の実装は以下の通りです。(はじめに\(x\)を\(a\)で割ってしまっている点にご注意ください。)
#include <iostream> #include <iomanip> #include <cmath> using namespace std; int main() { double a, b, x; cin >> a >> b >> x; x/=a; double y, rad, deg; if(x >= a*b/2.0) { // 水のかさが半分より大きい時 y = 2.*x/a-b; rad = atan((b-y)/a); } else { // 水のかさが半分未満の時 y = (2.*x) / b; rad = atan(b/y); } deg = rad * 180. / M_PI; cout << setprecision(12); cout << deg << endl; return 0; }