2 0 0 1 1 2 1 1 1 1 3 -1.5 0 0 0 0 1.5 0
0.71 0.00 0.75
平面最近点对求解,采用分治的方法,感觉做着做着就有cdq分治的感觉了,果然分治都是相通的啊,顺便一说,这里用到了鸽巢原理。
#include<cstdio> #include<stack> #include<ctime> #include<cmath> #include<queue> #include<cstring> #include<algorithm> using namespace std; typedef long long LL; const int INF = 2e9 + 10; const int maxn = 1e5 + 10; int n; struct point { double x, y; void read(){ scanf("%lf%lf", &x, &y); } bool operator<(const point&a)const { return x < a.x; } }a[maxn], b[maxn]; bool cmp(const point&a, const point&b) { return a.y < b.y; } double dis(point&a, point&b) { return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y)); } double solve(int l, int r) { if (l + 1 == r) { sort(a + l, a + r + 1, cmp); return dis(a[l], a[r]); } if (l + 2 == r) { sort(a + l, a + r + 1, cmp); return min(dis(a[l], a[l + 1]), min(dis(a[l], a[r]), dis(a[r], a[r - 1]))); } int mid = l + r >> 1, tot = 0; double d = min(solve(l, mid), solve(mid + 1, r)); for (int i = mid + 1; i <= r; i++) if (a[i].x - a[mid].x <= d) b[tot++] = a[i]; for (int i = l, j = 0; i <= mid; i++) { for (; j < tot&&a[i].y - b[j].y > d; j++); for (int k = j; k < tot&&b[k].y - a[i].y<d; k++) d = min(d, dis(a[i], b[k])); } for (int i = l, j = l, k = mid + 1; i <= r; i++) { if (j <= mid && (k>r || a[j].y < a[k].y)) b[i] = a[j++]; else b[i] = a[k++]; } for (int i = l; i <= r; i++) a[i] = b[i]; return d; } int main() { while (scanf("%d", &n), n) { for (int i = 0; i < n; i++) a[i].read(); sort(a, a + n); printf("%.2lf\n", solve(0, n - 1) / 2); } return 0; }