http://acm.hdu.edu.cn/showproblem.php?pid=1007
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
题意:给定平面上n个点,找其中的一对点,使得在n个点的所有点对中,该点对的距离最小。
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> using namespace std; #define N 110000 #define INF 0x3f3f3f3f #define met(a, b) memset (a, b, sizeof(a)) struct node { double x, y; }stu1[N], stu2[N]; bool cmpx (node a, node b) { return a.x < b.x; } bool cmpy (node a, node b) { return a.y < b.y; } int n; double dist (node a, node b) { return sqrt ((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y)); } double mindist (int l, int r) { if (l+1 == r) return dist(stu1[l], stu1[r]);///剩两个点的情况 if (l+2 == r)///剩三个点的情况 return min (dist(stu1[l], stu1[l+1]), min (dist(stu1[l], stu1[r]), dist(stu1[l+1], stu1[r]))); int mid = (l + r) / 2; double d = min (mindist (l, mid), mindist (mid+1, r));///左右递归 int k = 0; for (int i=l; i<=r; i++) if (fabs (stu1[i].x-stu1[mid].x) < d) stu2[k++] = stu1[i];///找到离中间线距离小于两遍的最短距离的点 sort (stu2, stu2+k, cmpy);///y坐标排序 for (int i=0; i<k; i++) for (int j=i+1; j<k; j++) {///两边各有一点之间的距离小于两遍的最小距离 if (dist(stu2[i], stu2[j]) >= d) break; d = min (d, dist(stu2[i], stu2[j])); } return d; } int main () { while (scanf ("%d", &n), n) { for (int i=0; i<n; i++) scanf ("%lf%lf", &stu1[i].x, &stu1[i].y); sort (stu1, stu1+n, cmpx); printf ("%.2f\n", mindist (0, n-1)/2); } return 0; }