AtCoder ABC 144 D - Water Bottle (400点) 解説
問題
問題文は本家サイトにあります:AtCoder ABC 144 D
問題概要
底面が1辺 $a\ \mathrm{cm}$ の正方形で高さが $b\ \mathrm{cm}$ の直方体型の水筒がある。ここに、体積 $x\ \mathrm{cm}^3$ の水を入れ、底面の一辺を軸として傾けたとき、水を溢れさせずに傾けることができる最大の角を度数法で答えなさい。
制約
入力はすべて整数
$1\leqq a \leqq 100$
$1\leqq b \leqq 100$
$1\leqq x \leqq a^2b$
解説
水筒を傾けて水があふれ出る直前の状態を、横から見た図を考えます。まずは水が結構入っている状態を考えましょう。
色のついた部分が水です。傾けた角が上の図の $\theta$ です。この $\theta$ を使って水の体積が出せれば、あとはそれを逆に解いて答えを求めることができます。
水の体積は、上の図の色のついた部分の面積に $a$ を掛ければいいので、面積を求めることを考えます。色のついた部分は台形なので、台形の面積を求めてもいいのですが、それよりも三角形 CDE の面積を考えたほうが楽でしょう。水面と地面は平行になっているはずなので、 $\angle \mathrm{ CDE }=\theta$ となることがわかります。
CD の長さは $a$ で、 CE の長さは $a\tan\theta$ です(参考:【基本】三角比の定義(直角三角形による定義))。なので、次のような式が成り立ちます。\[ (ab -\dfrac{1}{2}\times a\times a\tan\theta)\times a=x \]これを $\theta$ について解くと
\begin{eqnarray}
a^2b -\dfrac{1}{2}a^3\tan\theta&=& x \\[5pt]
\dfrac{1}{2}a^3\tan\theta&=& a^2b -x \\[5pt]
\tan\theta&=& \frac{2(a^2b -x)}{a^3} \\[5pt]
\theta&=& \arctan \frac{2(a^2b -x)}{a^3} \\[5pt]
\end{eqnarray}$\arctan$ は $\tan$ の逆関数です。
これが答えかと思いきや、水の量が少ない場合は、上側の空洞が三角形ではなくなってしまいます。なので、そのケースを別に考える必要があります。
上のような場合は、色のついた部分が三角形となるので、ここを直接考えたほうがいいでしょう。ここでも、水面と地面は平行だから、錯角が等しいので $\angle \mathrm{ AED }=\theta$ となります。
$\mathrm{ AD }=b$ で、 $\tan\theta=\dfrac{\mathrm{ AD } }{\mathrm{ AE } }$ だから $\mathrm{ AE }=\dfrac{b}{\tan\theta}$ となります。よって、次の式が成り立ちます。\[ \dfrac{1}{2}\times b\times \dfrac{b}{\tan\theta} \times a=x \]これを $\theta$ について解くと
\begin{eqnarray}
\dfrac{ab^2}{2\tan\theta}&=& x \\[5pt]
2x\tan\theta &=& ab^2 \\[5pt]
\theta &=& \arctan \frac{ab^2}{2x} \\[5pt]
\end{eqnarray}となります。
この2つのケースは、水の量が水筒の半分より多いかどうかでわかれるので、次のようなコードで書くことができます。提出 #8184215
#include <bits/stdc++.h>
using namespace std;
int main() {
double a, b, x, theta;
cin >> a >> b >> x;
if (x > a * a * b / 2) {
theta = atan(2 * (a * a * b - x) / (a * a * a));
} else {
theta = atan((a * b * b) / (2 * x));
}
double PI = 3.14159265358979;
theta = theta * 180 / PI;
cout << fixed << setprecision(10) << theta;
return 0;
}