結果
問題 |
No.96 圏外です。
|
ユーザー |
![]() |
提出日時 | 2025-04-16 01:12:50 |
言語 | PyPy3 (7.3.15) |
結果 |
AC
|
実行時間 | 720 ms / 5,000 ms |
コード長 | 3,875 bytes |
コンパイル時間 | 505 ms |
コンパイル使用メモリ | 82,572 KB |
実行使用メモリ | 133,688 KB |
最終ジャッジ日時 | 2025-04-16 01:14:22 |
合計ジャッジ時間 | 9,914 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge4 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 28 |
ソースコード
import math from collections import defaultdict class UnionFind: def __init__(self, size): self.parent = list(range(size)) self.rank = [0] * size def find(self, x): if self.parent[x] != x: self.parent[x] = self.find(self.parent[x]) return self.parent[x] def union(self, x, y): x_root = self.find(x) y_root = self.find(y) if x_root == y_root: return if self.rank[x_root] < self.rank[y_root]: self.parent[x_root] = y_root else: self.parent[y_root] = x_root if self.rank[x_root] == self.rank[y_root]: self.rank[x_root] += 1 def convex_hull(points): points = sorted(points) lower = [] for p in points: while len(lower) >= 2 and cross(lower[-2], lower[-1], p) <= 0: lower.pop() lower.append(p) upper = [] for p in reversed(points): while len(upper) >= 2 and cross(upper[-2], upper[-1], p) <= 0: upper.pop() upper.append(p) return lower[:-1] + upper[:-1] def cross(o, a, b): return (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0]) def rotating_calipers(hull): n = len(hull) if n <= 1: return 0.0 if n == 2: return math.hypot(hull[0][0] - hull[1][0], hull[0][1] - hull[1][1]) max_dist = 0.0 j = 1 for i in range(n): next_i = (i + 1) % n while True: next_j = (j + 1) % n dx = hull[next_i][0] - hull[i][0] dy = hull[next_i][1] - hull[i][1] dxj = hull[next_j][0] - hull[j][0] dyj = hull[next_j][1] - hull[j][1] cross_product = dx * dyj - dxj * dy if cross_product > 0: j = next_j else: break current_dist = math.hypot(hull[i][0] - hull[j][0], hull[i][1] - hull[j][1]) if current_dist > max_dist: max_dist = current_dist current_dist_next = math.hypot(hull[i][0] - hull[next_j][0], hull[i][1] - hull[next_j][1]) if current_dist_next > max_dist: max_dist = current_dist_next return max_dist def main(): import sys input = sys.stdin.read().split() ptr = 0 N = int(input[ptr]) ptr += 1 if N == 0: print("1.000000000") return points = [] for _ in range(N): x = int(input[ptr]) y = int(input[ptr + 1]) ptr += 2 points.append((x, y)) grid = defaultdict(list) for i in range(N): x, y = points[i] cell_x = x // 10 cell_y = y // 10 grid[(cell_x, cell_y)].append(i) uf = UnionFind(N) for i in range(N): x, y = points[i] cell_x = x // 10 cell_y = y // 10 for dx in (-1, 0, 1): for dy in (-1, 0, 1): neighbor_cell = (cell_x + dx, cell_y + dy) if neighbor_cell in grid: for j in grid[neighbor_cell]: if j > i: xj, yj = points[j] dx_ = x - xj dy_ = y - yj dist_sq = dx_ ** 2 + dy_ ** 2 if dist_sq <= 100: uf.union(i, j) roots = defaultdict(list) for i in range(N): root = uf.find(i) roots[root].append(points[i]) max_candidate = 0.0 for group in roots.values(): if len(group) == 0: continue hull = convex_hull(group) if len(hull) <= 1: diam = 0.0 else: diam = rotating_calipers(hull) candidate = diam + 2.0 if candidate > max_candidate: max_candidate = candidate print("{0:.9f}".format(max_candidate)) if __name__ == '__main__': main()