poj3714
洛谷P1257
这里有一步优化,对所有横坐标
i
∈
[
l
,
r
]
i\in[l,r]
i∈[l,r]之间满足
∣
a
[
i
]
.
x
−
a
[
m
i
d
]
.
x
∣
<
d
|a[i].x-a[mid].x|<d
∣a[i].x−a[mid].x∣<d的点,我们将y坐标从小到大排序,在之后遍历所有合格点之间的距离的时候,一旦
a
[
j
]
.
y
−
a
[
i
]
.
y
>
d
a[j].y-a[i].y>d
a[j].y−a[i].y>d就可以break。
ps:一定要用scanf
#include<iostream>
#include<vector>
#include<string.h>
#include<string>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define MAX 100005
#define ll long long
#define inf 10000000005
struct P {
double x, y, k;//k:0表示station 1表示agent
P(double a = 0, double b = 0, int kind = 0) { x = a, y = b, k = kind; }
}a[MAX * 2], t[MAX * 2];
bool cmp(P p1, P p2) {
if (p1.x == p2.x) return p1.y < p2.y;
else return p1.x < p2.x;
}
bool cmpy(P p1, P p2) {
return p1.y < p2.y;
}
double dist(P p1, P p2) {
if (p1.k == p2.k) return inf;
return sqrt((p1.x - p2.x)*(p1.x - p2.x) + (p1.y - p2.y)*(p1.y - p2.y));
}
ll N, n;
double merge(ll l, ll r) {
if (l == r)return inf;
if (l == r - 1) return dist(a[l], a[r]);
ll mid = (l + r) >> 1;
double d1 = merge(l, mid), d2 = merge(mid + 1, r), d = min(d1, d2);
int i, j, k = 0;
for (i = l; i <= r; i++) {
if (fabs(a[i].x - a[mid].x) < d)
t[k++] = a[i];
}
sort(t, t + k, cmpy);//x都符合要求,那么我们按y坐标从小到大排序
for (int i = 0; i < k; i++) {
for (int j = i + 1; j < k && t[j].y - t[i].y < d; j++) {
double dis = dist(t[i], t[j]);
d = min(d, dis);
}
}
return d;
}
int main() {
cin >> N;
while (N--) {
cin >> n;
for (int i = 0; i < 2 * n; i++) {
scanf("%lf%lf", &a[i].x, &a[i].y);
if (i < n)a[i].k = 0;
else a[i].k = 1;
}
sort(a, a + 2 * n, cmp);//打乱排列进行排序
printf("%.3f\n", merge(0, 2 * n - 1));
}
}