poj 3714 Raid 分治法求平面最近点对

缘起

日常浪费生命~ poj 3714 Raid

分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
平面上给你A、B两类点, 每类各N个. 定义一对点为一个点是A类点, 一个点是B类点. 那么显然可以组成
N^2对点, 问你哪对点距离最近?

【输入】
多样例. 每个样例开始于N(1 ≤ N ≤ 100000).然后N行每行2个非负整数x,y
(0 ≤ x ≤ 1000000000,0 ≤ y ≤ 1000000000)
然后再N行,每行2个非负整数, x,y 范围同上,表示B类点.

【输出】
每个样例输出最短点对的距离(精确到三位小数)

【样例输入】
2
4
0 0
0 1
1 0
1 1
2 2
2 3
3 2
3 3
4
0 0
0 0
0 0
0 0
0 0
0 0
0 0
0 0

【样例输出】
1.414
0.000

【限制】
5s

【1】中我们已经处理了计算几何中经典的平面最近点对问题. 本题是该经典问题的一个变式. 只需要在【1】的ac代码里面判断两个点的类别是不是一样就行了.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
//#include "stdafx.h"
#include <stdio.h>
#include <algorithm>
#include <math.h>
using namespace std;
//#define LOCAL
typedef long long LL;
#define SQUARE(x) ((x)*(x))
#define DBL_MAX 1.7e+300
const int maxn = 100005;
int n;

struct Point
{
LL x,y;
int type; // 点的类别
}p[maxn<<1];
int pp[maxn<<1];

bool cmpx(Point &a, Point &b)
{
return a.x<b.x;
}

double dis(int i, int j)
{
return sqrt(1.0*SQUARE(p[i].x-p[j].x)+ SQUARE(p[i].y-p[j].y));
}

bool cmpy(int a, int b)
{
return p[a].y<p[b].y;
}

double fz(int lo, int hi)
{
if (lo>=hi)
{
return DBL_MAX;
}
int mid = (lo+hi)>>1;
double a = fz(lo, mid), b = fz(mid+1, hi), ans;
ans = min(a,b);
int cnt = 0;
for (int i = lo; i<=hi; i++)
{
if (p[i].x>=p[mid].x-ans && p[i].x<=p[mid].x+ans)
{
pp[cnt++] = i;
}
}
sort(pp,pp+cnt, cmpy);
for (int i = 0; i<cnt-1; i++)
{
for (int j = i+1; j<cnt; j++)
{
if (p[pp[j]].y-p[pp[i]].y>=ans)
{
break;
}
else if (p[pp[i]].type!=p[pp[j]].type) // 如果不是同一类的点, 则优化ans
{
ans = min(ans, dis(pp[i], pp[j]));
}
}
}
return ans;
}

int main()
{
#ifdef LOCAL
freopen("d:\\data.in", "r", stdin);
//freopen("d:\\my.out", "w", stdout);
#endif
int kase;
scanf("%d", &kase);
while(kase--)
{
scanf("%d", &n);
for (int i = 0; i<(n<<1); i++)
{
scanf("%lld%lld", &p[i].x, &p[i].y);
p[i].type = i>=n;
}
sort(p,p+2*n, cmpx);
printf("%.3lf\n", fz(0, n*2-1));
}
return 0;
}

ac情况(G++编译错误, 用C++提交)

20886978 yfsyfs 3714 Accepted 4824K 2750MS C++ 1417B 2019-09-22 20:52:36

参考

【1】https://yfsyfs.github.io/2019/09/22/hdu-1007-Quoit-Design-%E6%9F%A5%E6%89%BE%E5%B9%B3%E9%9D%A2%E6%9C%80%E8%BF%91%E7%82%B9%E5%AF%B9/