//最近点对 //1.分: // 把所有点递归分到小于等于3个点 // 然后3个点或2个点两两之间Brute force找出最近的两点距离dlf, 和 drg,并返回这两点 //2.并: // 找出每分界线之间最短的dmid,跟据排序后X序列 // ^ // . . | . . . | // . .| . . . d // . . | . . . | // <-d ->| <-d-> v // // #include <iostream> #include <algorithm> #include <cmath> using std::cin; using std::cout; using std::sort; using std::sqrt; #define MAX 100 //#define _DEBUG__ struct Point { double x; double y; }; struct Point_Y { int index; Point point; }; int n = 0; Point *X = NULL; Point_Y * Y = NULL; bool cmpX(Point a, Point b) { return a.x < b.x; } bool cmpY(Point_Y a, Point_Y b) { return a.point.y < b.point.y; } void SortX() { if (X != NULL) sort(X, X + n, cmpX); #ifdef _DEBUG__ for (int i = 0; i < n; ++i) cout << "x=" << X[i].x << "y=" << X[i].y << "\n"; #endif } void Copy() { if (X != NULL && Y != NULL){ for (int i = 0; i < n; ++i){ Y[i].index = i; Y[i].point.x = X[i].x; Y[i].point.y = X[i].y; } } } void SortY() { if (Y != NULL) sort(Y, Y + n, cmpY); } double Distance(Point &a, Point &b) { return ((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); } double fabs(double a) { return a > 0.0 ? a : -a; } void Find_Close_Pair(Point_Y * Y, int low, int hight, Point &node_a, Point &node_b, double &dist) { if (hight - low == 1){//2点 node_a = X[low], node_b = X[hight]; dist = Distance(node_a, node_b); } else if(hight - low == 2){//3点 if (Distance(X[low], X[low + 1]) < Distance(X[low], X[hight]) && Distance(X[low], X[low + 1]) < Distance(X[low + 1], X[hight])) node_a = X[low], node_b = X[low + 1]; else if (Distance(X[low + 1], X[hight]) < Distance(X[low], X[hight])) node_a = X[low + 1], node_b = X[hight]; else node_a = X[low], node_b = X[hight]; dist = Distance(node_a, node_b); } else{//下面运用分治法 //分 int mid = (hight - low) / 2; Point_Y *XL = new Point_Y[mid + 1]; Point_Y *XR = new Point_Y[mid + 1]; int xl = 0, xr = 0; mid += low; for (int i = 0; i < hight - low + 1; ++i){ if (Y[i].index <= mid) XL[xl++] = Y[i]; else XR[xr++] = Y[i]; } Point nal, nbl, nar, nbr; double distl, distr; Find_Close_Pair(XL, low, mid, nal, nbl, distl); Find_Close_Pair(XR, mid + 1, hight, nar, nbr, distr); if (distl < distr) node_a = nal, node_b = nbl, dist = distl; else node_a = nar, node_b = nbr, dist = distr; //并 Point *Comb = new Point[hight - low + 1]; int count_comb = 0; for (int i = 0; i < hight - low + 1; ++i) if (fabs(X[mid].x - Y[i].point.x) < dist){//找出当前子集合中在离最中间的线(X[m].x) //横座标小于dist的当前子集合中所有点 Comb[count_comb].x = Y[i].point.x, Comb[count_comb].y = Y[i].point.y; count_comb++; } for (int i = 0; i < count_comb; ++i)//两两之间的距离 for (int j = i + 1; (j < count_comb) && (fabs(Comb[i].y - Comb[j].y) < dist); ++j) if (Distance(Comb[i], Comb[j]) < dist) node_a = Comb[i], node_b = Comb[j], dist = Distance(Comb[i], Comb[j]); delete []XL; delete []XR; delete []Comb; } } void Init() { for (int i = 0; i < n; ++i){ cin >> X[i].x >> X[i].y; } } void MinClosePair() { Init(); SortX(); Copy(); SortY(); Point node_a, node_b; double dist = 0.0; Find_Close_Pair(Y, 0, n - 1, node_a, node_b, dist); #ifdef __DEBUG__ cout << sqrt(dist) << '\n'; cout << "A (" << node_a.x << "," << node_a.y << ")\n"; cout << "B (" << node_b.x << "," << node_b.y << ")\n"; #endif printf("%.2lf\n", sqrt(dist) / 2.0); } int main(void) { while (cin >> n){ if (n == 0) break; X = new Point[n]; Y = new Point_Y[n]; MinClosePair(); delete []X; delete []Y; } return 0; }