1. 程式人生 > >HDU 1007 Quoit Design(分治)

HDU 1007 Quoit Design(分治)

題意:

有n個點,求最近的兩個點的距離的一半

思路:

首先,每個點比一下的演算法是不可取的,所以可以採取分治的思路,首先吧所有點按照x大小升序排列,這時可以找到一箇中點mid,這時圖被分為兩半,最近的兩個點可能在左邊或者右邊或者兩邊各一個邊,再分治找到兩邊的最小距離d,這時還沒有判斷如果是左右兩邊的點距離最小,那麼就在合併的時候,遍歷[l,r],查詢距離mid的x小於d的所有點,這時可以用兩層for直接暴力,但是如果這些點很多的話, n2n^2是會超時的,所以把這些點按照y排序,如果兩個點的y值相差大於d的話,就可以直接捨棄後面的點,也就是兩層for的第二層直接break,

#include
<bits/stdc++.h>
using namespace std; #define LL long long const int maxn = 1e5 + 5; const double inf = 1e20; struct Point{ double x, y; }p[maxn], tmp[maxn]; bool cmpX(Point a, Point b) { return a.x < b.x; } bool cmpY(Point a, Point b) { return a.y < b.y; } double getDis(Point a,
Point b) { return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y)); } double closePair(int l, int r) { double d = inf; if(l == r) return d; if(l + 1 == r) return getDis(p[l], p[r]); int mid = (l + r) >> 1; double d1 = closePair(l, mid); double d2 = closePair
(mid + 1, r); d = min(d1, d2); int len = 0; for (int i = l; i <= r; i ++) { if(fabs(p[mid].x - p[i].x) <= d) { tmp[len++] = p[i]; } } sort(tmp, tmp + len, cmpY); for (int i = 0; i < len; i ++) { for (int j = i + 1; j < len; j ++) { if(p[j].y - p[i].y < d) { d = min(d, getDis(tmp[i], tmp[j])); }else break; } } return d; } int main(int argc, char const *argv[]) { int T; while (scanf("%d", &T) && T) { for (int i = 1; i <= T; i ++) scanf("%lf %lf", &p[i].x, &p[i].y); sort(p + 1, p + T + 1, cmpX); printf("%.2lf\n", closePair(1, T)/2); } return 0; }