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));
}

posted @ 2021-02-12 13:06  喜欢李知恩IU  阅读(61)  评论(0)    收藏  举报