結果
問題 |
No.3154 convex polygon judge
|
ユーザー |
|
提出日時 | 2025-05-20 21:49:34 |
言語 | PyPy3 (7.3.15) |
結果 |
AC
|
実行時間 | 764 ms / 2,000 ms |
コード長 | 2,459 bytes |
コンパイル時間 | 237 ms |
コンパイル使用メモリ | 82,688 KB |
実行使用メモリ | 151,552 KB |
最終ジャッジ日時 | 2025-05-20 21:49:41 |
合計ジャッジ時間 | 6,411 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge4 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 44 |
ソースコード
#!/usr/bin/env python3 # 狭義凸 N 角形判定(偏角ソート版, 真三角形探索は O(N)) # 2025-05-20 import sys import math def cross(ax: int, ay: int, bx: int, by: int) -> int: """2D 外積 (a × b)""" return ax * by - ay * bx def pick_triangle(pts): """ 先頭 2 点 p0, p1 を固定し、残りを 1 回だけ走査して cross(p1-p0, pk-p0) ≠ 0 となる点 pk を探す。 見つかれば (p0, p1, pk) を返す。見つからなければ全点共線 → None。 ※ O(N)。 """ p0, p1 = pts[0], pts[1] x1, y1 = p1[0] - p0[0], p1[1] - p0[1] for pk in pts[2:]: xk, yk = pk[0] - p0[0], pk[1] - p0[1] if cross(x1, y1, xk, yk) != 0: return p0, p1, pk return None def main() -> None: data = list(map(int, sys.stdin.buffer.read().split())) if not data: return n, *rest = data pts = [(rest[i], rest[i + 1]) for i in range(0, 2 * n, 2)] # 点が 3 未満なら不可 if n < 3: print("No") return # O(N) で真三角形を 1 つ探す tri = pick_triangle(pts) if tri is None: print("No") # 全点共線 return # --- 以降は先ほどと同じ --- # 重心 cx = (tri[0][0] + tri[1][0] + tri[2][0]) / 3.0 cy = (tri[0][1] + tri[1][1] + tri[2][1]) / 3.0 # 偏角+距離でソート def key(p): ang = math.atan2(p[1] - cy, p[0] - cx) if ang < 0: # atan2 は [-π, π] を返すので 0‥2π に正規化 ang += 2 * math.pi dist2 = (p[0] - cx) ** 2 + (p[1] - cy) ** 2 return (ang, dist2) order = sorted(pts, key=key) # 隣接 3 点外積の符号を確認 sign = None m = len(order) for i in range(m): xA, yA = order[i] xB, yB = order[(i + 1) % m] xC, yC = order[(i + 2) % m] abx, aby = xB - xA, yB - yA bcx, bcy = xC - xB, yC - yB z = cross(abx, aby, bcx, bcy) if z == 0: # 共線が 1 組でもあれば狭義凸ならず print("No") return cur = 1 if z > 0 else -1 if sign is None: sign = cur # 1 つ目の曲がり方向を採用 elif sign != cur: # 曲がり方向が混在 → 非凸 print("No") return # ここまで来れば狭義凸 N 角形が可能 print("Yes") if __name__ == "__main__": main()