理解

转一篇博文

图示

最近点距

代码

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
#include <iostream>
#include <cstdio>
#include <math.h>
#include <cstring>
#include <algorithm>
using namespace std;
#define inf 0x3f3f3f3f
const int MAXN=100005;
// 点的结构体
struct dots
{
double x,y;
}point[MAXN];
int index[MAXN];
//比较函数,让点以x轴排序
bool cmpx(dots a,dots b){
return a.x<b.x;
}
//比较函数,按点的y值的大小排序点的id
bool cmpy_idx(int a,int b){
return point[a].y<point[b].y;
}
//距离函数,返回两点距离的平方
inline double dis(dots a, dots b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
//其实可以直接调用cmath里面的min,只是用inline函数会更快
inline double min(double a, double b){
return a<b?a:b;
}
// 分治算法求最近点对
double close_pair(int left,int right){
//若二分到同一个点,返回无穷大
if(left == right ) return inf;
//若二分到相邻点,返回其距离大小
if(left + 1 == right ) return dis(point[left],point[right]);
int mid = (left + right) >> 1;
//最近点对在left到mid之间 或者 在mid+1到right之间
double ans = min(close_pair(left,mid) , close_pair(mid+1,right));
int cnt=0;
//最近点对,一边在left一边在right的情况
//将,x轴范围在 point[mid].x - ans 到 point[mid].x + ans之间的点,标号,存在index数组中
for(int i = left ;i <= right ; i++)
if( point[i].x <= point[mid].x + ans && point[i].x >= point[mid].x - ans)
index[++cnt]=i;
//按点的y值的大小排序点的id
sort(index+1,index+1+cnt,cmpy_idx);
//暴力法求解合理范围内的点对距离
for(int i = 1; i <= cnt ; i++){
for(int j= i+1 ;j <= cnt ; j++){
if(point[index[j]].y - point[index[i]].y >= ans) break;
ans = min(ans, dis( point[index[j]] , point[index[i]] ) );
}
}
return ans;
}
//读取点的x,y值,并进行排序
void inint(int number){
for(int i=1;i <=number ;i++){
scanf("%lf%lf",&point[i].x,&point[i].y);
}
sort(point+1,point+1+number,cmpx);
}
int main(){
int N;
while(cin>>N,N!=0){
//N是点的个数
inint(N);
double ans=close_pair(1,N);//在HDU1007中需要除以2。
printf("%.2lf\n",ans);
}
return 0;
}

友情链接

HDU_1007