In the N points on a two-dimensional plane, how to quickly find the nearest pair of points is the problem of the nearest point.
A simple idea is to forcibly enumerate every two points and record the minimum distance. Obviously, the time complexity is O (n ^ 2 ).
This section describes an O (nlognlogn) algorithm. Actually, it is used hereSub-Governance. Divide the set S of N points on the given plane into two subsets S1 and S2, each of which has about n/2 points. Then, recursively find the closest point in each subset. Here, a key question is how to implement the merge steps in the Division and Control Law, that is, how to obtain the closest point in the original set S from the closest point of S1 and S2. If the two points are in S1 and S2, the problem becomes complicated.
To make the problem easier,First, consider one-dimensional scenarios.. In this case, the N points in S are degraded to n real numbers x1, x2,..., xn on the X axis. The closest point is the two real numbers with the smallest difference among the n real numbers. Obviously, you can sort the vertices in order and then perform linear scanning. However, in order to facilitate the promotion to two-dimensional situations, we try to solve this problem using the divide and conquer method.
Suppose we use M to divide s into S1 and S2 sets. In this way, for all P (points in S1) and Q (points in S2), there is P <q.
Recursively locate the closest point pairs {p1, p2} and {Q1, Q2} on S1 and S2, and set
D = min {| p1-p2 |, | q1-q2 |}
It is easy to know that the closest vertex in S is {p1, p2}, {Q1, Q2}, or a {Q3, P3}, as shown in.
If the closest point is {Q3, P3}, I .e. | p3-q3 | <D, then the distance between P3 and Q3 and M is not greater than D, and in the range (m-D, d] and (D, M + D] each have only one vertex. In this way, merge can be implemented in linear time.
In this case, the time complexity of the closest point in one dimension is O (nlogn ).
In two-dimensional scenariosSimilarly, the Division and control method is used, but the difficulty lies in how to achieve linear merge?
Visible, forming a 2D band interval with a maximum of N points. The merging time is at least N ^ 2 ,. However, vertices in P1 and P2 have the following sparse properties. For any point in P1, vertices in P2 must fall into a d x 2D rectangle, you only need to check up to six points (the Pigeon nest principle ).
In this way, the points in the band interval are sorted by Y coordinates and then scanned linearly. the time complexity of the merge is O (nlogn), which is almost linear.
I can't do it without practicing it. After thinking and referring to the online program, I completed the latest point-to-point program and successfully AC it on each OJ.
Poj3714
Zoj2107
Hdu1007
/** Closest point problem, time complexity: O (N * logn) */# include <iostream> # include <cstdio> # include <cstring> # include <cmath> # include <algorithm> using namespace STD; const double INF = 1e20; const int n= 100005; struct point {Double X; Double Y;} Point [N]; int N; int tmpt [N]; bool cmpxy (const point &, const point & B) {if (. x! = B. x) return. x <B. x; return. Y <B. y;} bool cmpy (const Int & A, const Int & B) {return point [A]. Y <point [B]. y;} double min (double A, double B) {return a <B? A: B;} double DIS (int I, Int J) {return SQRT (point [I]. x-point [J]. x) * (point [I]. x-point [J]. x) + (point [I]. y-point [J]. y) * (point [I]. y-point [J]. y);} double closest_pair (INT left, int right) {double D = inf; If (Left = right) return D; If (left + 1 = right) return DIS (left, right); int mid = (left + right)> 1; double d1 = closest_pair (left, mid); double D2 = closest_pair (Mid + 1, right); D = min (D1, D2); int I, j, k = 0; // separate the range for (I = left; I <= right; I ++) {If (FABS (point [Mid]. x-point [I]. x) <= d) tmpt [k ++] = I;} Sort (tmpt, tmpt + k, cmpy); // linear scan for (I = 0; I <K; I ++) {for (j = I + 1; j <K & point [tmpt [J]. y-point [tmpt [I]. Y <D; j ++) {double D3 = DIS (tmpt [I], tmpt [J]); If (D> D3) d = D3 ;}} return D;} int main () {While (true) {scanf ("% d", & N); If (n = 0) break; for (INT I = 0; I <n; I ++) scanf ("% lf", & point [I]. x, & point [I]. y); sort (point, point + N, cmpxy); printf ("%. 2lf \ n ", closest_pair (0, n-1)/2);} return 0 ;}