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. 入っている水のかさが半分以上の時

傾けていくと次のような状態で限界点を迎えます。

f:id:accha-n:20191029092549j:plain
水量が多い時

限界点では、図の通り、台形になっていることから台形の面積の公式により、水量を求め、図中の\(y\)を逆算します。


\begin{align}
\frac{(y+b)*a}{2} &= \frac{x}{a} \\\
y &= \frac{2x}{a^{2}} - b
\end{align}

求める\(\theta\)は、 $$\theta = \tan^{-1} (\frac{b-y}{a})$$ となります。

2-2. 入っている水のかさが半分以下の時

f:id:accha-n:20191029092935j:plain
水量が少ない時

限界点では、先ほどとは異なり、三角形の形状になります。先ほどと同様に、水量が変化しないことから図中の\(y\)を逆算すると、


\begin{align}
\frac{b*y}{2} &= \frac{x}{a} \\\
y &= \frac{2x}{ab}
\end{align}

図より、求める\(\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;
}