题解:最近点对问题,使用平面上的点分治思想
因为n比较大,所以枚举所有点是行不通的,考虑基于分治算法的思想
假设把所有的点按x坐标分成了左右两半,那么最近点对的距离就是下面二者的最小值
1.2点p和q同属于左半边或者右半边时点对(p,q)的距离
2.2点p和q属于不同区域时点对(p,q)的距离(这里还有很多优化处理)
复杂度分析:递归的深度为O(logn),而每一层有O(n)个操作,所以总的复杂度是O(nlogn)。
#include<bits/stdc++.h>
using namespace std;
typedef pair<double,double>P;
const int MAXN=1e4+50;
const int INF=1e4+30;
int N;
P A[MAXN];
bool compare_y(P a,P b)
{
return a.second<b.second;
}
double closest_pair(P *a,int n)
{
if(n<=1){
return INF;
}
int m=n/2;
double x=a[m].first;
double d=min(closest_pair(a,m),closest_pair(a+m,n-m));
sort(a,a+n,compare_y);
vector<P>b;
for(int i=0;i<n;i++){
if(fabs(a[i].first-x)>=d){
continue;
}
for(int j=0;j<b.size();j++){
double dx=a[i].first-b[b.size()-j-1].first;
double dy=a[i].second-b[b.size()-j-1].second;
if(dy>=d){
break;
}
d=min(d,sqrt(dx*dx+dy*dy));
}
b.push_back(a[i]);
}
return d;
}
void solve()
{
sort(A,A+N);
double ans=closest_pair(A,N);
if(ans>10000){
printf("INFINITY\n");
}else{
printf("%.4f\n",ans);
}
}
int main()
{
while(scanf("%d",&N)!=EOF&&N){
for(int i=0;i<N;i++){
scanf("%lf%lf",&A[i].first,&A[i].second);
}
solve();
}
return 0;
}