传送门:洛谷-平面最近点对
给定平面上n个点,找出其中的一对点的距离,使得在这n个点的所有点对中,该距离为所有点对中最小的。
2≤n≤200000
一、分治
按x排序,左右分治,边界处理一下就好了。
代码:
#include
#include
#include
#include
#include
#define db double
const int INF=0x7fffffff;
using namespace std;
typedef long long ll;
const int N=2e5+10;
struct P{
int x,y;
}p[N];
int n,in[N],cnt;
inline db sqr(int x){return (db)x*(db)x;}
inline db fab(db x){return x<0 ? -x:x;}
inline db min(db a,db b){return ainline db dist(P a,P b){return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));}
bool cmp(const P &a,const P &b){
if(a.x==b.x){
return a.yreturn a.xbool cmq(const int &a,const int &b){return p[a].yinline db merge(int l,int r)
{
db d=INF;
if(l==r) return d;
if(l+1==r) return dist(p[l],p[r]);
int mid=(l+r)>>1;
db pa=merge(l,mid);
db pb=merge(mid+1,r);
d=min(pa,pb);
cnt=0;
for(int i=l;i<=r;i++){
if(fab(p[i].x-p[mid].x)//<=
in[++cnt]=i;
}
}
sort(in+1,in+cnt+1,cmq);
for(int i=1;i<=cnt;i++){
for(int j=i+1;j<=cnt && p[in[j]].y-p[in[i]].yreturn d;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d%d",&p[i].x,&p[i].y);
}
sort(p+1,p+n+1,cmp);
printf("%.4lf\n",merge(1,n));
return 0;
}
二、扫描
按y排序,从上往下扫,优化看代码。
代码:
#include
#include
#include
#include
#include
#define db double
const int INF=0x7fffffff;
using namespace std;
typedef long long ll;
const int N=2e5+10;
struct P{
int x,y;
}p[N];
db ans;
int n,head[N],to[N],nxt[N],cnt,tot;
inline db sqr(int x){return (db)x*(db)x;}
inline db fab(db x){return x<0 ? -x:x;}
inline db min(db a,db b){return areturn sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));}
inline void lk(int u,int v)
{
nxt[++tot]=head[u];head[u]=tot;to[tot]=v;
}
inline bool cmq(const P &a,const P &b){
if(a.y==b.y) return a.xx;
return a.yy;
}
int main(){
ans=INF;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d%d",&p[i].x,&p[i].y);
}
sort(p+1,p+n+1,cmq);
lk(1,1);++cnt;
for(int i=2;i<=n;i++){
if(p[i].y!=p[i-1].y){
++cnt;
}else{
ans=min(ans,(db)(p[i].x-p[i-1].x));
}
lk(cnt,i);
}
for(int i=1;iint mx=i+1;
while(mx<=cnt && (db)(p[to[head[mx]]].y-p[to[head[i]]].y)<=ans){
int qw=head[mx];
for(int e,k=head[i];k && qw ;k=nxt[k]){
int ty=to[k];
for(;qw;qw=nxt[qw]){
while(nxt[qw]!=0 && p[to[nxt[qw]]].x>=p[ty].x){
qw=nxt[qw];
}
e=to[qw];
if(p[e].x<=p[ty].x){
ans=min(dist(p[e],p[ty]),ans);
break;
}
ans=min(dist(p[e],p[ty]),ans);
}
}
mx++;
}
}
printf("%.4lf\n",ans);
return 0;
}