平面最近点对(分治)
本题言简意赅,给n个点,求最近点对(
Luogu
poj(略有不同)
题解:
这题初看令人眩晕,有效信息两两点的距离就有
正解是一个经典分治,本题分治特点是利用分治答案来进行分治,按x排序,按x分治,枚举mid左右ans范围内的点,把这些点按y排序,y坐标相差不超过ans的点统计答案(横着的日字划分,可证每个点统计答案不超过6个),总复杂度
具体的说,本题是一个经典的模型,本来
代码(Luogu):
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <math.h>
using namespace std;
typedef long double ld;
const int N=2e5+50;
const ld le=1e-7;
const ld INf=2000000000.0;
struct Point{
int x,y;
Point(){}
}po[N],tmp[N];
int n;
ld ans=INf;
bool cmpx(Point a,Point b){return a.x<b.x;}
bool cmpy(Point a,Point b){return a.y<b.y;}
inline int wdabs(int a){return (a>0?a:(-a));}
inline ld sqr(ld a){return a*a;}
inline ld dis(int a,int b){return sqrt(sqr(tmp[a].x-tmp[b].x)+sqr(tmp[a].y-tmp[b].y));}
void solve(int l,int r)
{
if(l==r) return;
int mid=(l+r)/2;
solve(l,mid);
solve(mid+1,r);
int d=ans,cnt=0;d+=1;
for(int i=l;i<=r;i++)
if(wdabs(po[i].x-po[mid].x)<=d)
tmp[++cnt]=po[i];
sort(tmp+1,tmp+1+cnt,cmpy);
for(int i=1;i<=cnt;i++)
{
for(int j=i+1;tmp[j].y-tmp[i].y<=d && j<=cnt;j++)
ans=min(ans,dis(i,j));
}
return;
}
int main()
{
ans=INf;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d%d",&po[i].x,&po[i].y);
sort(po+1,po+1+n,cmpx);
solve(1,n);
printf("%.4Lf\n",ans);
return 0;
}