結果
| 問題 |
No.199 星を描こう
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2016-04-11 16:06:52 |
| 言語 | Go (1.23.4) |
| 結果 |
AC
|
| 実行時間 | 2 ms / 2,000 ms |
| コード長 | 3,493 bytes |
| コンパイル時間 | 14,524 ms |
| コンパイル使用メモリ | 218,844 KB |
| 実行使用メモリ | 5,248 KB |
| 最終ジャッジ日時 | 2024-12-30 03:48:34 |
| 合計ジャッジ時間 | 15,609 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 25 |
ソースコード
package main
import (
"bufio"
"fmt"
"math"
"math/cmplx"
"os"
"strconv"
)
var sc = bufio.NewScanner(os.Stdin)
func main() {
sc.Split(bufio.ScanWords)
var ps []complex128
for i := 0; i < 5; i++ {
ps = append(ps, complex(nextFloat(), nextFloat()))
}
if len(solve2(ps)) == 5 {
fmt.Println("YES")
return
}
fmt.Println("NO")
}
func nextLine() string {
sc.Scan()
return sc.Text()
}
func nextInt() int {
i, _ := strconv.Atoi(nextLine())
return i
}
func solve2(ps []complex128) []complex128 {
lp, rp := leftMost(ps), rightMost(ps)
ret := make([]complex128, 2, 500)
ret[0], ret[1] = lp, rp
return append(ret, solve(lp, rp, ps)...)
}
func solve(lp, rp complex128, ps []complex128) []complex128 {
if len(ps) == 0 {
return nil
}
a, b, c := equationL(lp, rp)
updown, div := [][]complex128{make([]complex128, 0, 50), make([]complex128, 0, 50)}, make([]complex128, 2)
maxU, maxD := float64(0), float64(0)
ret := make([]complex128, 0, 100)
for _, p := range ps {
d := distance(a, b, c, p)
switch side := posL(p, lp, rp); {
case side > 0:
if d > maxU {
maxU, div[0] = d, p
}
updown[0] = append(updown[0], p)
case side < 0:
if d > maxD {
maxD, div[1] = d, p
}
updown[1] = append(updown[1], p)
}
}
if len(updown[0]) > 0 {
ret = append(ret, div[0])
}
if len(updown[1]) > 0 {
ret = append(ret, div[1])
}
left := [][]complex128{updown[0][:0], updown[1][:0]}
right := [][]complex128{make([]complex128, 0, 25), make([]complex128, 0, 25)}
tri := [][]complex128{[]complex128{lp, rp, div[0]}, []complex128{lp, rp, div[1]}}
inter := []complex128{nearestP(div[0], lp, rp), nearestP(div[1], lp, rp)}
for i := 0; i < 2; i++ {
for _, p := range updown[i] {
if inPolygon(p, tri[i]) {
continue
}
if posL(p, inter[i], div[i]) > 0 {
left[i] = append(left[i], p)
continue
}
right[i] = append(right[i], p)
}
}
ret = append(ret, solve(lp, div[0], left[0])...)
ret = append(ret, solve(div[0], rp, right[0])...)
ret = append(ret, solve(rp, div[1], left[1])...)
ret = append(ret, solve(div[1], lp, right[1])...)
return ret
}
func leftMost(ps []complex128) complex128 {
p := ps[0]
for _, v := range ps[1:] {
if real(v) < real(p) {
p = v
}
}
return p
}
func rightMost(ps []complex128) complex128 {
p := ps[0]
for _, v := range ps[1:] {
if real(v) > real(p) {
p = v
}
}
return p
}
func equationL(a, b complex128) (float64, float64, float64) {
return imag(b) - imag(a), real(a) - real(b), imag(a)*real(b) - real(a)*imag(b)
}
func distance(a, b, c float64, z complex128) float64 {
return math.Abs(a*real(z)+b*imag(z)+c) / math.Sqrt(a*a+b*b)
}
func posL(p, a, b complex128) int {
ba, pa := b-a, p-a
c := real(ba)*imag(pa) - imag(ba)*real(pa)
switch {
case c > 0:
return 1 // left
case c < 0:
return -1 // right
default:
return 0 // on the line
}
}
func nearestP(p, a, b complex128) complex128 {
ab, ba, pa, pb := a-b, b-a, p-a, p-b
if dot(ba, pa) < 0 {
return a
}
if dot(ab, pb) < 0 {
return b
}
return a + complex(dot(pa, ba)/(real(ba)*real(ba)+imag(ba)*imag(ba)), 0)*ba
}
func dot(a, b complex128) float64 {
return real(a * cmplx.Conj(b))
}
func inPolygon(p complex128, ps []complex128) bool {
ps = append(ps, ps[0])
sign := posL(p, ps[0], ps[1])
for i, v := range ps[1 : len(ps)-1] {
if sign*posL(p, v, ps[i+2]) < 0 {
return false
}
}
return true
}
func nextFloat() float64 {
f, _ := strconv.ParseFloat(nextLine(), 64)
return f
}