P1429 平面最近点对(加强版)
题意:
平面坐标上有\(n\)个坐标点,你需要找出距离最近的点对。(\(n\leq 2*10^5\))
题解:
按照\(x\)坐标排序,分治,分治左区间和右区间的最小值,算出了左区间和右区间的最值的最小的为\(d\),那么对于点对\(x\)坐标横跨左右区间的,我们先把区间内距离中点的横坐标小于\(d\)的全部放在一起,然后将这些点按y坐标排序,最后暴力求就可以了。
#include "bits/stdc++.h"
const int N=2e5+5;
const double inf=0x3f3f3f3f;
using namespace std;
int n,cnt[N];
double ans;
struct node{
double x,y;
}a[N];
bool cmp(int x,int y){
return a[x].y<a[y].y;
}
double dis(int l,int r){
double x=a[l].x,y=a[l].y;
double xx=a[r].x,yy=a[r].y;
double ans=(x-xx)*(x-xx)+(y-yy)*(y-yy);
return sqrt(ans);
}
double merge(int l,int r){
double d=inf;
if(l==r) return d;
if(l+1==r) return dis(l,r);
int mid=l+r>>1;
double d1=merge(l,mid);
double d2=merge(mid+1,r);
d=min(d1,d2);
int i,j,k=0;
for(i=l;i<=r;i++)
if(fabs(a[mid].x)-a[i].x<d) cnt[++k]=i;
sort(cnt+1,cnt+1+k,cmp);
for(i=1;i<=k;i++)
for(int j=i+1;j<=k&&a[cnt[j]].y-a[cnt[i]].y<d;j++){
double d3=dis(cnt[i],cnt[j]);
if(d>d3) d=d3;
}
return d;
}
bool cmp1(node x,node y){
if(x.x==y.x) return x.y<y.y;
return x.x<y.x;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%lf %lf",&a[i].x,&a[i].y);
sort(a+1,a+1+n,cmp1);
printf("%.4lf\n",merge(1,n));
}
要拿牌啊

浙公网安备 33010602011771号