AtCoder ABC 144 D - Water Bottle (Go)
irisruneです。コンテストはE問題の解法がどうにも思いつきませんでしたが、水パフォは出ました。
問題
直球の数学問題ですが、D問題だけあって割と面倒な問題です。
package main import ( "bufio" "fmt" "math" "os" "strconv" ) var sc *bufio.Scanner func nextStr() string { sc.Scan() return sc.Text() } func nextInt() int { sc.Scan() i, e := strconv.Atoi(sc.Text()) if e != nil { panic(e) } return i } func main() { sc = bufio.NewScanner(os.Stdin) sc.Buffer(make([]byte, 0), 1000000001*3) sc.Split(bufio.ScanWords) a, b, x := nextInt(), nextInt(), nextInt() v0 := a * a * b v1 := v0 - x switch { case v1 <= x: fmt.Println(math.Atan((float64(v1)*2.0)/float64(a*a*a)) * (180.0 / math.Pi)) case v1 > x: fmt.Println(90.0 - (math.Atan((float64(x)*2.0)/float64(a*b*b)) * (180.0 / math.Pi))) } }
図を描かないことには始まらない問題なので、まずは図を描いてみます。既にネタバレが見えていますが、すぐに思い浮かぶのは左側の図になると思います。
この直方体の水筒において、横の辺の長さが、縦の辺の長さが、描写上省略されている奥行きはです。また、水色の領域は水の入っている領域のため体積がです。描写上水筒そのものではなく水位を傾けて表現していますが、水位と上辺の成す角度が求める角度となります。
ここで左側の図について考えると、水筒の体積や求める角度について以下の等式が成り立ちます。
これより角度を直接求めることができますが、図を2つ示していたことからわかるように場合分けが必要となります。場合分けの条件はがより大きいか小さいかです。大きい場合は前述の数式で解くことができ、小さい場合はで解くことができます(正確には90°から引いた角度が求める角度となります)。
雑記
- 奥行きを省略した図を描いて考える場合、水の体積を面積に置き換えた方が考えやすいかもしれません。
- 数学問題は検索でどうにかなることも多いですが、この問題については三角関数の扱い方がわかっていないと検索もままならない印象です。
- 弧度法とラジアンの変換まで求められているのでやはり数学的知識の比重が大きめだと思います。
- 公式解説によれば角度を直接求めるより2分法を用いる方が素直な解き方らしいです。いずれにせよ三角関数を用いる必要はあります。