问题:平面上有个点,求这
个点的最近的两个点之间的距离。
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1007
分析:本问题用到了二分思想,把平面分为两部分,两边的点数目大致相等,然后分别计算。关键是合并步骤,这里
假设两个半面的最近点对分别是和
,并设
,那么只需要找出
在区间
内的点即可,然后对于每一个点再上下枚举范围在内的点,取最小的距离即可,这样利用分治法
的时间复杂度为。
代码:
#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <math.h>
using namespace std;
typedef long long LL;
const double INF = 1e20;
const int N = 100005;
struct Point
{
double x,y;
};
Point p[N];
int t[N];
double dist(Point A,Point B)
{
return sqrt((A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y));
}
bool cmpxy(const Point& A,const Point& B)
{
if(A.x != B.x) return A.x < B.x;
return A.y < B.y;
}
bool cmpy(const int& a,const int& b)
{
return p[a].y < p[b].y;
}
double dfs(int L,int R)
{
double d = INF;
if(L == R) return d;
if(L + 1 == R) return dist(p[L],p[R]);
int mid = (L + R) >> 1;
double d1 = dfs(L,mid);
double d2 = dfs(mid + 1,R);
d = min(d1,d2);
int cnt = 0;
for(int i=L; i<=R; i++)
{
if(fabs(p[mid].x - p[i].x) <= d)
t[cnt++] = i;
}
sort(t,t+cnt,cmpy);
for(int i=0; i<cnt; i++)
{
for(int j=i+1; j<cnt && p[t[j]].y - p[t[i]].y < d; j++)
{
double tmp = dist(p[t[j]],p[t[i]]);
d = min(d,tmp);
}
}
return d;
}
int main()
{
int n;
while(~scanf("%d",&n))
{
if(n == 0) break;
for(int i=0; i<n; i++)
scanf("%lf%lf",&p[i].x,&p[i].y);
sort(p,p+n,cmpxy);
double ans = dfs(0,n-1);
printf("%.2lf\n",ans / 2);
}
return 0;
}