题意是给你n个点,要扔一个圆,在任何情况这个圆都不能覆盖两个以上的点。求这个圆的最大半径。
这个最大直径就是最近的点对距离的一半。算法导论讲的很详细也给出了正确性的证明。
#include <bits/stdc++.h> using namespace std; #define maxn 111111 #define INF 1e15 struct node { double x, y; } p[maxn], tmp[maxn]; int cnt, n; bool cmp1 (const node &a, const node &b) { return a.x < b.x || (a.x == b.x && a.y < b.y); } bool cmp2 (const node &a, const node &b) { return a.y < b.y; } double dis (node a, node b) { double xx = a.x-b.x, yy = a.y-b.y; return sqrt (xx*xx + yy*yy); } double solve (int l, int r) { double d = INF; if (l == r) return d; if (r-l == 1) { return dis (p[r], p[l]); } int mid = (l+r)>>1; d = min (solve (l, mid), solve (mid+1, r)); int cnt = 0; for (int i = l; i <= r; i++) { if (fabs (p[mid].x-p[i].x) < d) { tmp[cnt++] = p[i]; } } sort (tmp, tmp+cnt, cmp2); for (int i = 0; i < cnt; i++) { for (int j = i+1, tot = 1; j < cnt && tot <= 7 && tmp[j].y-tmp[i].y < d; j++) { d = min (d, dis(tmp[i], tmp[j])); } } return d; } int main () { //freopen ("in", "r", stdin); while (scanf ("%d", &n) == 1 && n) { for (int i = 0; i < n; i++) { scanf ("%lf%lf", &p[i].x, &p[i].y); } sort (p, p+n, cmp1); printf ("%.2f\n", solve (0, n-1)/2.0); } return 0; }