pku 3714(最近点对)
1 /* 2 * 题目要求:求最近点对(一个点在station内,一个点在agent内) 3 */ 4 5 #include <cmath> 6 #include <cstdio> 7 #include <cstdlib> 8 #include <iostream> 9 #include <algorithm> 10 11 using namespace std; 12 13 const int N = 200005; 14 const double INF = 1e20; 15 16 struct point { 17 int f; 18 double x; 19 double y; 20 }p[N]; 21 int tmp[N]; 22 23 double dis(point A, point B) { 24 return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y)); 25 } 26 27 int cmp(const point &a, const point &b) { 28 if (a.x != b.x) return a.x < b.x; 29 return a.y < b.y; 30 } 31 32 int cmp1(const int &a, const int &b) { 33 return p[a].y < p[b].y; 34 } 35 36 double min(double a, double b) { 37 return a > b ? b : a; 38 } 39 40 double closestPair(int left, int right) { 41 double d = INF; 42 if (left == right) return d; //同属station点,返回无穷大 43 if (left+1 == right) return d; //同属agent点,返回无穷大 44 int mid = (left + right) >> 1; 45 double d1 = closestPair(left, mid); 46 double d2 = closestPair(mid+1, right); 47 d = min(d1, d2); 48 int k = 0; 49 for (int i=left; i<=right; ++i) { 50 if (fabs(p[mid].x- p[i].x) <= d) tmp[k++] = i; 51 } 52 sort(tmp, tmp+k, cmp1); 53 for (int i=0; i<k; ++i) {//只有当一个点为station的点,另一个点为agent点时,才计算两点距离 54 for (int j=i+1; j<k && p[tmp[j]].y-p[tmp[i]].y<d && ((p[tmp[j]].f==0&&p[tmp[i]].f==1)||(p[tmp[j]].f==1&&p[tmp[i]].f==0)); ++j) { 55 double d3 = dis(p[tmp[i]], p[tmp[j]]); 56 if (d3 < d) d = d3; 57 } 58 } 59 return d; 60 } 61 62 int main() { 63 int n, t; 64 scanf ("%d", &t); 65 while (t--) { 66 scanf ("%d", &n); 67 for (int i=0; i<n; ++i) { 68 scanf ("%lf%lf", &p[i].x, &p[i].y); 69 p[i].f = 0; //标志为station的点 70 } 71 for (int i=n; i<n+n; ++i) { 72 scanf ("%lf%lf", &p[i].x, &p[i].y); 73 p[i].f = 1; //标志为agent的点 74 } 75 if (n == 1) printf ("%.lf\n", dis(p[0], p[1]));//只有两个点,直接算 76 else { 77 sort(p, p+n+n, cmp); 78 double ans = closestPair(0, n+n-1); 79 printf ("%.3lf\n", ans); 80 } 81 } 82 return 0; 83 }