HDU 1007 Quoit Design(分治)
阿新 • • 發佈:2018-12-18
題意:
有n個點,求最近的兩個點的距離的一半
思路:
首先,每個點比一下的演算法是不可取的,所以可以採取分治的思路,首先吧所有點按照x大小升序排列,這時可以找到一箇中點mid,這時圖被分為兩半,最近的兩個點可能在左邊或者右邊或者兩邊各一個邊,再分治找到兩邊的最小距離d,這時還沒有判斷如果是左右兩邊的點距離最小,那麼就在合併的時候,遍歷[l,r],查詢距離mid的x小於d的所有點,這時可以用兩層for直接暴力,但是如果這些點很多的話, 是會超時的,所以把這些點按照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;
}