AOJ2057 The Closest Circle
問題リンク The Closest Circle
- 概要
N個の円が重なることなく散らばっている。円同士が最も近づいている場所の距離を求めよ。円同士の距離は、
中心間の距離−円1の半径−円2の半径
とする。なお、N個の円の中の半径の最小値をRとすると、全ての円の半径rはR <= r <= 2*Rを満たす。
2 <= N <= 10^5
- 解法
ランダム回転+ソートで解きました。
まず、適当な角度(1°〜44°)で回転させます。座標でソートします。そして、ソート順序における前後100個くらいの円だけ比較すれば答えが求まるんじゃない?みたいな軽いノリで実装したらAcceptしちゃいました。
この後調子に乗って、比較する円の個数を減らしたところ、前後5個程度でAcceptできるみたいです。
- ソース
import java.util.Arrays; import java.util.Random; //The Closest Circle public class AOJ2057 { class Scanner { int nextInt() { try { int c = System.in.read(); while (c != '-' && (c < '0' || '9' < c)) c = System.in.read(); if (c == '-') return -nextInt(); int res = 0; do { res *= 10; res += c - '0'; c = System.in.read(); } while ('0' <= c && c <= '9'); return res; } catch (Exception e) { return -1; } } double nextDouble() { return Double.parseDouble(next()); } String next() { try { StringBuilder res = new StringBuilder(""); int c = System.in.read(); while (Character.isWhitespace(c)) c = System.in.read(); do { res.append((char) c); } while (!Character.isWhitespace(c = System.in.read())); return res.toString(); } catch (Exception e) { return null; } } } class R implements Comparable<R>{ double x, y, r; public R(double x, double y, double r) { this.x = x; this.y = y; this.r = r; } public int compareTo(R o) { if(Math.abs(x-o.x)<EPS)return (int)Math.signum(y-o.y); return (int)Math.signum(x-o.x); } } double EPS = 1e-8; void run(){ Scanner sc = new Scanner(); Random rand = new Random(System.currentTimeMillis()); for(;;){ int n = sc.nextInt(); if(n==0)break; int rot = rand.nextInt(44)+1; double sin = Math.sin(rot*Math.PI/180), cos = Math.cos(rot*Math.PI/180); R[] rs = new R[n]; for(int i=0;i<n;i++){ double r = sc.nextDouble(), x = sc.nextDouble(), y = sc.nextDouble(); rs[i] = new R(cos*x-sin*y, sin*x+cos*y, r); } Arrays.sort(rs); double res = 1L<<60; for(int i=0;i<n;i++){ int t = Math.min(n, i+5); for(int j=i+1;j<t;j++){ res = Math.min(res, Math.sqrt((rs[i].x-rs[j].x)*(rs[i].x-rs[j].x) + (rs[i].y-rs[j].y)*(rs[i].y-rs[j].y))-rs[i].r-rs[j].r); } } System.out.printf("%.9f\n", res); } } public static void main(String[] args) { new AOJ2057().run(); } }