问题:
给定平面上N个点的坐标,找出距离最近的两个点。
方法1:
两两点比较,寻找最近的两个点对,复杂度O(N^2),
方法2:
1、先对N个点的坐标按照X值排序,递归计算左右两部分的最近点对,分别为MinDist(left)、MinDist(right),计算MDist=min (MinDist(left),MinDist(right))
2、找出带状区域。如果一个点对的距离小于MDist,那么他们一定在一个MDist*(2*MDist)的区域内。一个MDist*(2*MDist)的区域最多只有8个点。
3、按照y 坐标,对带状区域内的顶点进行排序。
4、将带状区域的点计算距离与MDist比较。去最小值。
代码如下:
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<math.h>
using namespace std;
#define min(a,b) (((a)<(b))?(a):(b))
struct Point
{
int x;
int y;
};
struct rem
{
int start;
int end;
}position;
int flag=0;
double Dist_left;
double Dist_right;
double minTemp;
Point *select;
bool operator <(const Point a,const Point b)
{
if (flag==0)
{
return a.x<b.x;
}
else
{
return a.y<b.y;
}
}
double compute_Dist(Point point1,Point point2)
{
return sqrt((point1.x-point2.x)*(point1.x-point2.x)+(point1.y-point2.y)*(point1.y-point2.y));
}
double Dist(Point point[],int start,int end,double minDist)
{
int mid,i,j=0,k;
double a,b,c;
if ((end-start+1)>3)
{
mid=(end+start)/2;
Dist_left=Dist(point,start,mid,minDist);
Dist_right=Dist(point,mid+1,end,minDist);
minDist=min(Dist_left,Dist_right);
for (i=start;i<=end;i++)
{
if (abs(point[mid].x-point[i].x)<=minDist)
{
select[j]=point[i];
j++;
}
}
//坐标按照y排序
sort(select,select+j);
//计算
for (i=0;i<j;i++)
{
for (k=i+1;(k<j)&&k<=(i+7);k++)
{
if (compute_Dist(select[i],select[k])<minDist)
{
minDist=compute_Dist(select[i],select[k]);
position.start=i;
position.end=k;
}
}
}
return minDist;
}
if ((end-start+1)==3)
{
a=compute_Dist(point[start],point[start+1]);
b=compute_Dist(point[start],point[end]);
c=compute_Dist(point[start+1],point[end]);
minDist=min(a,b);
minDist=min(minDist,c);
if (flag==1)
{
flag++;
minTemp=minDist;
}
if (minDist==a)
{
if (minDist<=minTemp)
{
minTemp=minDist;
position.start=start;
position.end=start+1;
}
}
else
{
if (minDist==b)
{
if (minDist<=minTemp)
{
minTemp=minDist;
position.start=start;
position.end=end;
}
}
else
{
if (minDist<=minTemp)
{
minTemp=minDist;
position.start=start+1;
position.end=end;
}
}
}
}
else
{
minDist=compute_Dist(point[start],point[end]);
if (flag==1)
{
flag++;
minTemp=minDist;
}
if (minDist<=minTemp)
{
minTemp=minDist;
position.start=start;
position.end=end;
}
}
return minDist;
}
int main()
{
int N;
int i,j=0;
int k;
int mid;
double MinDist;
Point *point;
int temp=0;
double MinDist_left,MinDist_right;
cout<<"请输入点对的个数:";
cin>>N;
point=(Point*)malloc(sizeof(Point)*(N+1));
select=(Point*)malloc(sizeof(Point)*(N+1));
cout<<"请输入"<<N<<"个点对:"<<endl;
for (i=0;i<N;i++)
{
cin>>point[i].x;
cin>>point[i].y;
}
cout<<endl;
sort(point,point+N);
flag++;
setprecision(4);//精度为3
if (N<=3)
{
MinDist=Dist(point,0,N-1,MinDist);
// cout<<setprecision(4)<<MinDist<<"....."<<endl;
// cout<<point[position.start].x<<" "<<point[position.start].y<<endl;
// cout<<point[position.end].x<<" "<<point[position.end].y<<endl;
}
else
{
//找出左右两部分的MinDist
mid=(N-1)/2;
MinDist_left=Dist(point,0,mid,MinDist);
MinDist_right=Dist(point,mid+1,N-1,MinDist);
/*cout<<setprecision(4)<<MinDist_left<<"....."<<setprecision(4)<<MinDist_right<<"<<<<>>>"<<min(MinDist_left,MinDist_right)<<endl;*/
minTemp=min(MinDist_left,MinDist_right);
// cout<<point[position.start].x<<" "<<point[position.start].y<<endl;
// cout<<point[position.end].x<<" "<<point[position.end].y<<endl;
//带状区域
for (i=0;i<N;i++)
{
if (abs(point[mid].x-point[i].x)<=minTemp)
{
select[j]=point[i];
j++;
}
}
//坐标按照y排序
sort(select,select+j);
//计算
for (i=0;i<j;i++)
{
for (k=i+1;(k<j)&&k<=(i+7);k++)
{
if (compute_Dist(select[i],select[k])<minTemp)
{
temp++;
minTemp=compute_Dist(select[i],select[k]);
position.start=i;
position.end=k;
}
}
}
}
if (temp==0)
{
cout<<"最近点对:"<<endl;
cout<<point[position.start].x<<" "<<point[position.start].y<<endl;
cout<<point[position.end].x<<" "<<point[position.end].y<<endl;
cout<<"distance: "<<minTemp<<endl;
}
else
{
cout<<"最近点对:"<<endl;
cout<<select[position.start].x<<" "<<select[position.start].y<<endl;
cout<<select[position.end].x<<" "<<select[position.end].y<<endl;
cout<<"distance: "<<minTemp<<endl;
}
free(point);
return 0;
}
程序运行结果:
请输入点对的个数:14
请输入14个点对:
1 8
3 10
5 12
-10 0
-8 0
-7 0
-20 0
-18 0
-14 0
-16 0
-12 0
-5 2
-3 4
-1 6
最近点对:
-8 0
-7 0
distance: 1