经典的最接近点对问题
首先我们将所有的点对x坐标排序,然后采用分治将mid左右两边的最短距离ans求出来,然后我们将mid左右两边的x的距离小于ans的点选出,对其y坐标进行排序即可
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const double INF=2<<20;
struct Point{
double x,y;
Point(){}
Point(double _x,double _y)
{
x=_x;y=_y;
}
Point operator -(const Point &b)const
{
return Point(x-b.x,y-b.y);
}
double operator *(const Point &b)const
{
return x*b.x+y*b.y;
}
bool operator <(const Point &b)const
{
return x<b.x;
}
};
Point p[11111],p1[11111];
double dis(Point a,Point b)
{
return sqrt((a-b)*(a-b));
}
bool cmp(Point a,Point b)
{
return a.y<b.y;
}
double close(int l,int r)
{
if(l==r) return INF;
if(r-l==1) return dis(p[l],p[r]);
int mid=(l+r)/2;
double ans=min(close(l,mid),close(mid+1,r));
int num=0;
for(int i=l;i<=r;i++)
{
if(p[i].x>p[mid].x-ans&&p[i].x<p[mid].x+ans) p1[num++]=p[i];
}
sort(p1,p1+num,cmp);
for(int i=0;i<num;i++)
{
for(int j=i+1;j<num;j++)
ans=min(dis(p1[i],p1[j]),ans);
}
return ans;
}
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%lf%lf",&p[i].x,&p[i].y);
sort(p,p+n);
printf("%.4lf\n",close(0,n-1));
return 0;
}