POJ 3714 Raid 近期對點題解
阿新 • • 發佈:2018-12-01
本題是一般近期對點求解。略微新增點限定:有兩個集合點,要求不同集合中的點的近期對。
那麼就新增一個推斷。假設是同一個集合中的點,那麼就返回最大值。其它和一般的近期對點解法一樣。
注意:本題資料有重合點。那麼就要防止分類的時候溢位。
Geeks上的近期對的程式是無法處理有重合點的情況的。
#include <stdio.h> #include <stdlib.h> #include <float.h> #include <math.h> #include <algorithm> #include <string.h> using std::sort; struct Point { int x, y; int whichSet; }; inline int xCmp(const void *a, const void *b) { const Point *a1 = static_cast<const Point *>(a); const Point *b1 = static_cast<const Point *>(b); return a1->x - b1->x; } inline int xCmp2(const Point &a, const Point &b) { return a.x < b.x; } inline int yCmp2(const Point &a, const Point &b) { return a.y < b.y; } inline int yCmp(const void *a, const void *b) { const Point *a1 = static_cast<const Point *> (a); const Point *b1 = static_cast<const Point *> (b); return a1->y - b1->y; } inline float dist(Point &a, Point &b) { if (a.whichSet == b.whichSet) return FLT_MAX; float xd = (float)(a.x - b.x); float yd = (float)(a.y - b.y); return sqrtf(xd*xd + yd*yd); } float bruteForce(Point P[], int n) { float m = FLT_MAX; for (int i = 0; i < n; ++i) { for (int j = i+1; j < n; ++j) { float d = dist(P[i], P[j]); if (d < m) m = d; } } return m; } inline float mMin(float x, float y) { return x < y? x : y; } float stripClosest(Point strip[], int n, float d) { for (int i = 0; i < n; i++) { for (int j = i+1; j < n && strip[j].y -strip[i].y < d; j++) { float t = dist(strip[i], strip[j]); if (t < d) d = t; } } return d; } float closestUtil(Point Px[], Point Py[], int n) { if (n <= 3) return bruteForce(Px, n); int m = n >> 1; Point midPoint = Px[m]; Point *PyL = new Point[m+1]; Point *PyR = new Point[n-m-1]; int le = 0, ri = 0; for (int i = 0; i < n; i++) {//修正bug:新增le<m+1推斷。防止反覆點。引起溢位 if (Py[i].x <= midPoint.x && le < m+1) PyL[le++] = Py[i]; else PyR[ri++] = Py[i]; } float dl = closestUtil(Px, PyL, le);//m+1); float dr = closestUtil(Px+m+1, PyR, ri);//n-m-1); float d = mMin(dl, dr); Point *strip = new Point[n]; int j = 0; for (int i = 0; i < n; i++) { if (fabsf(float(Py[i].x - midPoint.x)) < d) strip[j++] = Py[i]; } d = mMin(d, stripClosest(strip, j, d)); delete [] strip; delete [] PyL; delete [] PyR; return d; } float closest(Point P[], int n) { Point *Px = new Point[n]; Point *Py = new Point[n]; memcpy(Px, P, n * sizeof(Point)); memcpy(Py, P, n * sizeof(Point)); //qsort(Px, n, sizeof(Point), xCmp); sort(Px, Px+n, xCmp2); //qsort(Py, n, sizeof(Point), yCmp); sort(Py, Py+n, yCmp2); float d = closestUtil(Px, Py, n); delete [] Px; delete [] Py; return d; } int main() { int T, n; scanf("%d", &T); while (T--) { scanf("%d", &n); Point *P = new Point[n<<1]; for (int i = 0; i < n; i++) { scanf("%d %d", &P[i].x, &P[i].y); P[i].whichSet = 1; } for (int i = n; i < (n<<1); i++) { scanf("%d %d", &P[i].x, &P[i].y); P[i].whichSet = 2; } printf("%.3f\n", closest(P, n<<1)); delete [] P; } return 0; }