题意,给出n个点的坐标,找出两点间最近的距离,如果小于10000就输出INFINITY。
纯暴力是会超时的,所以得另辟蹊径,用分治算法。
递归思路将点按坐标排序后,分成两块处理,最近的距离不是在两块中的一块中,就会存在于跨越中线的点对中。
查找跨越中线的点比较麻烦,之前已经求出两块中的最小距离,只要在x范围在[m-d,m+d]的点中找对,更新最小距离,最后返回最小距离即可。
代码:
/* * Author: illuz <iilluzen[at]gmail.com> * Blog: http://blog.csdn.net/hcbbt * File: uva10245.cpp * Lauguage: C/C++ * Create Date: 2013-09-04 19:57:26 * Descripton: UVA 10245 The Closest Pair Problem, partitation */ #include <cstdio> #include <cstdlib> #include <cmath> #include <algorithm> using namespace std; #define rep(i, n) for (int i = 0; i < (n); i++) #define sqr(x) ((x) * (x)) #define dis(i, j) (sqrt(sqr(p[i].x - p[j].x) + sqr(p[i].y - p[j].y))) const int MAXN = 10010; struct Point { double x; double y; } p[MAXN]; int n, t[MAXN]; double Min; bool cmp1(Point a, Point b) { return a.x < b.x; } bool cmp2(int a, int b) { return p[a].y < p[b].y; } double solve(int l, int r) { if (l == r) return 0xfffffff; if (l + 1 == r) return dis(l, r); int mid = (l + r) / 2; double d = min(solve(l, mid), solve(mid + 1, r)); int c = 0; for (int i = l; i <= r; i++) if (fabs(p[mid].x - p[i].x) <= d) t[c++] = i; sort(t, t + c, cmp2); for (int i = 0; i < c; i++) for (int j = i + 1; j < c && p[t[j]].y - p[t[i]].y < d; j++) { double td = dis(t[i], t[j]); if (d - td > 1e-9) d = td; } return d; } int main() { while (scanf("%d", &n) && n) { rep(i, n) scanf("%lf%lf", &p[i].x, &p[i].y); sort(p, p + n, cmp1); Min = solve(0, n - 1); if (Min - 10000 <= 1e-9) printf("%.4lf ", Min); else printf("INFINITY "); } return 0; }