[Luogu1429]平面最近点对(加强版)
题目大意:
平面最近点对。
思路:
分治。
首先将所有点排序
每次把当前区间分为两半,递归求解两个区间内部的情况,然后枚举区间两边的点。
1 #include<cmath> 2 #include<cstdio> 3 #include<cctype> 4 #include<algorithm> 5 inline int getint() { 6 register char ch; 7 while(!isdigit(ch=getchar())); 8 register int x=ch^'0'; 9 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 10 return x; 11 } 12 typedef std::pair<double,double> Point; 13 const int N=200000; 14 Point p[N]; 15 int num[N]; 16 double ans=1e10; 17 inline double sqr(const double &x) { 18 return x*x; 19 } 20 inline double dis(const Point &a,const Point &b) { 21 return sqrt(sqr(std::abs(a.first-b.first))+sqr(std::abs(a.second-b.second))); 22 } 23 void solve(const int &l,const int &r) { 24 if(l==r) return; 25 const int mid=(l+r)/2; 26 solve(l,mid);1`6 27 solve(mid+1,r); 28 num[0]=0; 29 for(register int i=mid+1;i<=r;i++) { 30 if(p[i].first-p[mid].first<ans) { 31 num[++num[0]]=i; 32 } 33 } 34 for(register int i=l;i<=mid;i++) { 35 if(p[mid].first-p[i].first<ans) { 36 for(register int j=1;j<=num[0];j++) { 37 ans=std::min(ans,dis(p[i],p[num[j]])); 38 } 39 } 40 } 41 } 42 int main() { 43 const int n=getint(); 44 for(register int i=0;i<n;i++) { 45 scanf("%lf%lf",&p[i].first,&p[i].second); 46 } 47 std::sort(&p[0],&p[n]); 48 solve(0,n-1); 49 printf("%.4f\n",ans); 50 return 0; 51 }