平面最近对点

给定平面上n个点,找出其中的一对点的距离,使得在这n个点的所有点对中,该距离为所有点对中最小的。

yy了一下,想了一个分治。按x排序点,记\(k = min(mindist(left,mid),mindist(mid,right))\) 大概就是划分平面,然后合并时单疼了,在确定中间边界时,我认为如果\(dist(P(i),P(mid)) > k\)就可以直接确定边界了,然而,WA一个点,然后手造了一组数据。
5
1 1
2 3
2 5
3 5
3 1
答案应该是1,然而我的是2.

然后发现按x排序用这个卡边界太紧了,换成$ abs(P[i].x - P[mid].x) > k$ 然后发现自己的数据对了,就过了。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 5000000;
struct Point{
	double x,y;
	Point (int x,int y):x(x),y(y){}
	Point(){x = 0;y = 0;}
}P[maxn];

bool CMP(Point A,Point B)
{
	return A.x < B.x ||(A.x == B.x &&A.y < B.y);
}

double dist(Point A,Point B)
{
	return sqrt((A.x - B.x )*(A.x - B.x) +(A.y - B.y )*(A.y - B.y ));
}
const double INF = 1e9;
double solve(int l,int r)
{
	if(r - l < 1) return INF;
	if(r - l == 1) return dist(P[l],P[r]);
	int k = (l+r)>>1;
	double ans = min(solve(l,k),solve(k+1,r));
	int ll = l,rr= r;
	for(int i = k;i >=l;i--)
		if(fabs(P[i].x - P[k].x )> ans){
			ll = i;
			break;
		}
	for(int i = k;i <= r;i++)
		if(fabs(P[i].x -P[k].x) > ans){
			rr = i;
			break;
		}
	for(int i =  ll;i <= rr;i++)
		for(int j = i+1;j <= rr;j++)
			ans = min(ans,dist(P[i],P[j]));
	return ans;
}
int main()
{
	int n;cin>>n;
	for(int i = 0;i < n;i++){
		double x,y;
		cin>>x>>y;
		P[i] = Point(x,y);
	}
	sort(P,P+n,CMP);
	double ans = INF;
	ans = min(ans,solve(0,n-1));
	printf("%.4lf",ans);
	return 0;
}
posted @ 2017-06-07 14:17  rsqppp  阅读(158)  评论(0)    收藏  举报