Description
对于平面上散布的 n 个点 p1, p2, …, pn, 称 d = min { || pi-pj ||, 1 ≤ i < j ≤ n } 为其最近点对距离.
本题对于给定的 n 个平面点, 请计算其最近点对距离.
Input
有多个测试用例, 每个测试用例由两部分组成. 测试用例的第一部分是一个大于 1 且不超过 10000 的正整数 n, 第二部分是 n 对绝对值不超过 10000 的整数 xi, yi, i=1,2,…,n, 表示平面上的点的横坐标和纵坐标.
输入直至没有数据为止.
Output
对于每个测试用例, 在一行上输出一个最多有 6 个有效数字的实数, 表示给定点集的最近点对距离. 注意: 输出行上不能有前缀和后缀空格.
Sample Input
2
0 0
1 0
Sample Output
1
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#define maxn 100100
using namespace std;
struct Point{
double x,y;
}p[maxn];
int num[maxn];
bool cmpx(Point a,Point b){
if (a.x == b.x) return a.y < b.y;
else return a.x < b.x;
}
bool cmpy(int a,int b)//按y递增排序
{
return p[a].y < p[b].y;
}
double dis(int i,int j){
return sqrt((p[i].x - p[j].x) * (p[i].x - p[j].x) +
(p[i].y - p[j].y) * (p[i].y - p[j].y));
}
double find(int l,int r){
if (l + 1 == r) return dis(l,r);
if (l + 2 == r) return min(min(dis(l + 1,r),dis(l,l + 1)),dis(l,r));
int mid = (l + r) / 2;
double ans = min(find(l,mid),find(mid + 1,r));
int cnt = 0;
for (int i = l; i <= r; i ++){
if (fabs(p[i].x - p[mid].x) <= ans)
num[cnt ++] = i;
}
sort(num,num+cnt,cmpy);
for (int i = 0; i < cnt;i ++){
for (int j = i + 1; j < cnt; j ++){
if (fabs(p[num[j]].y - p[num[i]].y) > ans) break;
ans = min(ans,dis(num[i],num[j]));
}
}
return ans;
}
int main()
{
int n;
while (~scanf("%d",&n) && n){
for (int i = 0; i < n; i ++){
scanf("%lf%lf",&p[i].x,&p[i].y);
}
sort(p,p + n,cmpx);
cout<<find(0,n-1)<<endl;
}
return 0;
}