题目大意:给 n 个整点,求其最近点对距离。
算法思路:
第一步,将点 1 到点 n-1 按距离点 0 由近及远排序,重编号点 1 到点 n-1;
第二步,设当前最小距离 answer := Distance(Point_0, Point_1),从点 1 到点 n-2 依次进行以下操作;
第三步,对于点 i,从点 i+1 到点 n-1 依次查询与点 i 的距离,若更近则更新当前最小距离 answer;
第四步,对于点对 (Point_i, Point_j),若有
D
i
s
t
a
n
c
e
(
P
o
i
n
t
0
,
P
o
i
n
t
j
)
−
D
i
s
t
a
n
c
e
(
P
o
i
n
t
0
,
P
o
i
n
t
i
)
>
a
n
s
w
e
r
Distance(Point_0, Point_j) - Distance(Point_0, Point_i) > answer
Distance(Point0,Pointj)−Distance(Point0,Pointi)>answer
则对于点 k (j < k < n),有
D
i
s
t
a
n
c
e
(
P
o
i
n
t
i
,
P
o
i
n
t
k
)
>
D
i
s
t
a
n
c
e
(
P
o
i
n
t
0
,
P
o
i
n
t
k
)
−
D
i
s
t
a
n
c
e
(
P
o
i
n
t
0
,
P
o
i
n
t
i
)
>
D
i
s
t
a
n
c
e
(
P
o
i
n
t
0
,
P
o
i
n
t
j
)
−
D
i
s
t
a
n
c
e
(
P
o
i
n
t
0
,
P
o
i
n
t
i
)
>
a
n
s
w
e
r
\begin{matrix} Distance(Point_i, Point_k) &> &Distance(Point_0, Point_k) - Distance(Point_0, Point_i) \\ &> &Distance(Point_0, Point_j) - Distance(Point_0, Point_i) \\ &> &answer \end{matrix}
Distance(Pointi,Pointk)>>>Distance(Point0,Pointk)−Distance(Point0,Pointi)Distance(Point0,Pointj)−Distance(Point0,Pointi)answer
距离必远于当前最小距离,跳过。
测试结果显示,对于随机稀疏数据,该算法表现与 O(nlogn) 级别算法相差不大;对于构造密集数据,该算法退化明显。
在算法初始时,可以随机调换点 0,以防止出现通过构造点 0 位置的数据使算法运行效率降低的情况。不过,既然点 0 位置是构造出的,那么其他点的位置很大可能是整齐有序的,在此情况下该算法运行效率不高,故该优化意义不大。
代码如下:
#include<algorithm>
#include<math.h>
#include<stdio.h>
#define MAX_N (100005)
#define Distance(x0,y0,x1,y1) (sqrt(((x1)-(x0))*((x1)-(x0))+((y1)-(y0))*((y1)-(y0))))
struct POINT
{
int x,y;
double d0;
}xy[MAX_N];
bool cmp(POINT p,POINT q)
{
return p.d0<q.d0;
}
int main()
{
int n;
double ans;
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d %d",&xy[i].x,&xy[i].y);
for(int i=1;i<n;i++)
xy[i].d0=Distance((double)xy[0].x,(double)xy[0].y,(double)xy[i].x,(double)xy[i].y);
std::sort(xy+1,xy+n,cmp);
ans=xy[1].d0;
for(int i=1;i<n;i++)
for(int j=i+1;j<n&&xy[j].d0-xy[i].d0<ans;j++)
if(Distance((double)xy[i].x,(double)xy[i].y,(double)xy[j].x,(double)xy[j].y)<ans)
ans=Distance((double)xy[i].x,(double)xy[i].y,(double)xy[j].x,(double)xy[j].y);
printf("%.2lf",ans);
return 0;
}