思路
如果是求一组点中的倆个点的最小距离:
把这一组点按横坐标从小到大排列好,分成两半,分别求最小距离,选倆者间小的设为d。但这不一定是答案,有可能两侧各选一个点,这倆个点的距离可能最小。所以在mid 两侧d的范围内各找一点计算距离,得出答案。
两个组的话,只需加个变量标记属于哪个组即可
代码
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
using namespace std;
int n;
struct node {
double x, y, z;
};
node p[200005];
bool cmp(node a, node b) {
if (a.x == b.x) return a.y < b.y;
return a.x < b.x;
}
double dis(int p1, int p2) {
return sqrt((p[p1].x - p[p2].x) * (p[p1].x - p[p2].x) + (p[p1].y - p[p2].y) * (p[p1].y - p[p2].y));
}
double func(int l, int r) {
if (l == r) {
return 2100000000;
}
if (l + 1 == r) {
if (p[l].z != p[r].z) return dis(l, r);
return 2100000000;
}
int mid = (l + r) / 2;
double d = min(func(l, mid), func(mid + 1, r));
for (int i = mid; i >= l && p[mid].x - p[i].x < d; i--) {
for (int j = mid + 1; j <= r && p[j].x - p[mid].x < d; j++) {
if (p[i].z != p[j].z) d = min(d, dis(i, j));
}
}
return d;
}
int main() {
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%lf%lf", &p[i].x, &p[i].y);
p[i].z = 1;
}
for (int i = 2 * n - 1; i >= n; i--) {
scanf("%lf%lf", &p[i].x, &p[i].y);
p[i].z = 2;
}
sort(p, p + 2 * n, cmp);
double ans = func(0, 2 * n - 1);
printf("%.3lf\n", ans);
return 0;
}