// The closest pair problem (recent point problem) // PC/Ultraviolet IDs: 111402/10245, popularity: A, success rate: Low Level: 2 // verdict: accepted // submission date: 2011-11-09 // UV Run Time: 0.240 S // All Rights Reserved (c) 2011, Qiu. Metaphysis # Yeah dot net // [solution] // typical problem. You can use the O (nlgn) Splitting Algorithm. For details, see Thomas H. cormen introduction to algorithms // section 2nd of Chapter 33rd of version 4th. Although the algorithm is easy to understand, it still takes some effort to implement it. However, after self-implementation, the understanding of the algorithm is further deepened, continuous practice, I think this is the only shortcut to Improving the ability. # Include the maximum number of <iostream> # include <algorithm> # include <cstring> # include <iomanip> # include <cmath> using namespace STD; # define maxn 10000 // points. # Define maxdistance (1e10) // The "infinite" distance value, which must be set according to the specific application. Struct point {Double X; Double Y ;}; point points [maxn]; // records coordinate data of a point. Int pointsnumber; // the total number of points. // Calculate the distance between two points, only the sum of squares of the distance. Inline double caldistance (point a, point B) {return (. x-B. x) * (. x-B. x) + (. y-B. y) * (. y-B. y);} // divide and conquer method to find the distance between the nearest point. Double closestdistance (int p [], int Pn, int X [], int XN, int y [], int yn) {// exit of recursive call, when the number of points after splitting is less than or equal to three, use the exhaustive method to calculate the nearest distance. Note that the initial distance should be // set to "infinite". The specific value of "infinite" should be set based on the specific application. If (PN <= 3) {double distance = maxdistance; For (INT I = 0; I <PN-1; I ++) for (Int J = I + 1; j <PN; j ++) {double TMP = caldistance (points [p [I], points [p [J]); distance = min (distance, TMP);} return distance;} // decomposition: divides the Point Set P into two sets: PL and PR. And obtain the corresponding XL, xr, YL, and yr. Int pl [maxn], PLN, PR [maxn], PRN; int XL [maxn], xln, xr [maxn], XRN; int yl [maxn], yln, yr [maxn], yrn; // indicates whether a vertex is in the specified set Pl. At the beginning, all vertices are not in the PL set. Bool inpl [maxn]; memset (inpl, false, sizeof (inpl); // divides the array P into a set of close PL and PR. All vertices in PL are online L or on the left side of L, // all vertices in PR are online L or on the right side of L. Array X is divided into two arrays, XL and XR, which contain vertices in // PL and pr respectively, and are sorted in a monotonically ascending order of X coordinates. Similarly, array y is divided into two arrays, yl // and yr, which contain vertices in PL and pr respectively, and are sorted in the monotonically ascending order of Y coordinates. For XL, xr, // YL, YR, because the X and Y parameters are sorted, you only need to split the corresponding points from them and do not need to sort them again, // after splitting, the sorting remains unchanged, which is the key to obtaining the O (nlgn) running time. Otherwise, if the sorting is performed again, the run time is O (N (lgn) ^ 2 ). Int middle = Pn/2; PLN = xln = middle; For (INT I = 0; I <PLN; I ++) {pl [I] = XL [I] = x [I]; inpl [x [I] = true;} PRN = XRN = (PN-middle ); for (INT I = 0; I <PRN; I ++) PR [I] = XR [I] = x [I + middle]; // Based on the set to which a vertex belongs, divide yl and yr. Yln = yrn = 0; For (INT I = 0; I <YN; I ++) if (inpl [Y [I]) YL [yln ++] = Y [I]; elseyr [yrn ++] = Y [I]; // solution: After Dividing P into PL and PR, perform Two recursive calls to find the nearest point in PL and the nearest point in PR. Double distancel = closestdistance (PL, PLN, XL, xln, YL, yln); double distancer = closestdistance (PR, PRN, xr, XRN, YR, yrn); // merge: the closest point is either a distance point found by a recursive call, or a point that is composed of a vertex in PL // and a vertex in PR, the algorithm determines whether there is a point whose distance is smaller than distance. Double mindistance = min (distancel, distancer); // create an array y ', it is the array obtained after removing all vertices in the/area of the array y that are not in the vertical band with a width of 2 * mindistance. The array y' is sorted by Y coordinate in the same order as Y. Int tmpy [maxn], tmpyn = 0; For (INT I = 0; I <YN; I ++) if (FABS (points [Y [I]. x-points [x [Middle]. x) <= mindistance) tmpy [tmpyn ++] = Y [I]; // For each vertex P in array y, the algorithm tries to find the point within the mindistance unit of P in Y. Only // you need to consider the 7 points followed by P in Y. The algorithm calculates the distance from P to the seven points, and records the tmpdistance distance from all vertices of y. Double tmpdistance = maxdistance; For (INT I = 0; I <tmpyn; I ++) {int Top = (I + 7) <tmpyn? (I + 7): (tmpyn-1); For (Int J = I + 1; j <= top; j ++) {double TMP = caldistance (points [tmpy [I], points [tmpy [J]); tmpdistance = min (tmpdistance, TMP );}} // If tmpdistance is smaller than mindistance, a point closer to the nearest point found/out based on recursive calls is indeed contained in the vertical band region. Therefore, the vertex pair and its distance from tmpdistance are returned. Otherwise, the nearest vertex found in the recursive call and its distance from mindistance are returned. Return min (mindistance, tmpdistance);} bool cmpx (int A, int B) {return points [A]. x <points [B]. x;} bool cmpy (int A, int B) {return points [A]. Y <points [B]. y;} double calclosestdistance () {// prepare the initial conditions. Note that in this solution, only the sequence numbers of each vertex are saved in the array, not the coordinates of the vertex, // This reduces the data replication time without affecting the algorithm implementation. Int P [maxn], PN; int X [maxn], xn; int y [maxn], yn; // assign an initial value. Pn = xn = YN = pointsnumber; For (INT I = 0; I <pointsnumber; I ++) P [I] = x [I] = Y [I] = I; // pre-sort by X and Y. Sort (x, x + Xn, cmpx); sort (Y, Y + YN, cmpy); // call the grouping algorithm. Return closestdistance (p, Pn, X, xn, Y, yn);} int main (int ac, char * AV []) {cout. precision (4); cout. SETF (IOs: Fixed | IOs: showpoint); While (CIN> pointsnumber, pointsnumber) {for (INT I = 0; I <pointsnumber; I ++) cin> points [I]. x> points [I]. y; double mindistance = SQRT (calclosestdistance (); If (mindistance> 10000.0) cout <"infinity" <Endl; elsecout <mindistance <Endl ;} return 0 ;}