平面最近对点
给定平面上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;
}

浙公网安备 33010602011771号