7-3 哪两个点之间的距离最近[A]
设P={(x1,y1),(x2,y2),⋯,(x**n,y**n)}是平面上散列的n个点的集合。请编写程序找出集合中距离最近的点对。严格地说,相同距离的最近点对可能不止一对,为了简单期间只找出第一对最近点对即可。
原题连接 PTA
参考文章算法分析与设计——最近点对问题
输入格式:
输入第一行给出一个正整数n
,表示平面上的点数。随后n行,每行给出一个实数对,每个实数对表示一个点的纵横坐标值,其中第1数表示横坐标,第2数表示纵坐标。
输出格式:
输出最近点对中两个点的坐标和它们之间的距离。如果 x1+y1<=x2+y2
则按
(x1,y1),(x2,y2),miniDist=Distance
输出结果,否则按
(x2,y2),(x1,y1),miniDist=Distance
输出结果。
其中x1
,y1
,x2
,y2
是保留两位小数的实数,Distance
是保留3位小数的实数
输入样例:
5
1.00 1.00
2.00 0.00
0.00 2.00
0.50 0.60
-1.00 2.00
输出样例:
(0.50,0.60),(1.00,1.00),miniDist=0.640
#include<iostream>
#include<cmath>
using namespace std;
class Point
{
public:
double x;
double y;
Point(double x, double y)
{
this->x = x;
this->y = y;
}
Point()
{
this->x = 0;
this->y = 0;
}
void print()
{
printf("(%.2f,%.2f),",this->x,this->y);
}
void set()
{
scanf("%lf %lf",&this->x, &this->y);
}
};
void QuickSort(Point *arr, int low, int high)
{
if (low < high)
{
int i = low, j = high;
Point k = arr[low];
while (i < j)
{
while(i < j && arr[j].x >= k.x)
{
j--;
}
if(i < j)
{
arr[i++] = arr[j];
}
while(i < j && arr[i].x < k.x)
{
i++;
}
if(i < j)
{
arr[j--] = arr[i];
}
}
arr[i] = k;
QuickSort(arr, low, i - 1);
QuickSort(arr, i + 1, high);
}
}
double Distance(Point a,Point b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double minDistance(Point p[], int low, int high, Point ret[])
{
double d1,d2,d3,delta;
int ma = 0;
Point mp[high-low+1],temp1[2],temp2[2],temp3[2];
if(high - low == 1)//只有两个点的情况,两点以及两点距离为答案
{
ret[0] = p[0];
ret[1] = p[1];
return Distance(ret[0],ret[1]);
}
else if(high - low == 2)//有三个点的情况
{
d1=Distance(p[low],p[low+1]);
d2=Distance(p[low+1],p[high]);
d3=Distance(p[low],p[high]);
if((d1 < d2) && (d1 < d3))
{
ret[0] = p[low];
ret[1] = p[low+1];
return d1;
}
else if(d2<d3)
{
ret[0] = p[low+1];
ret[1] = p[high];
return d2;
}
else {
ret[0] = p[low];
ret[1] = p[high];
return d3;
}
}
else//大于三个点递归解决
{
int mid=(low+high)/2;//中位数大概位置
d1 = minDistance(p,low,mid,ret);//左半平面
temp1[0] = ret[0];
temp1[1] = ret[1];
d2 = minDistance(p,mid+1,high,ret);//右半平面
temp2[0] = ret[0];
temp2[1] = ret[1];
if(d1 < d2)//给delta赋值为左右平面最小的值
{
delta = d1;
ret[0] = temp1[0];
ret[1] = temp1[1];
}
else
{
delta = d2;
ret[0] = temp2[0];
ret[1] = temp2[1];
}
//把符合条件的点放入mp数组
for(int i = mid; (i >= low) && (fabs(p[mid].x - p[i].x) < delta) && (fabs(p[mid].y - p[i].y < delta)); i--)
{
mp[ma++] = p[i];
}
for(int i = mid + 1; (i <= high) && (fabs(p[mid].x - p[i].x) < delta) && (fabs(p[mid].y - p[i].y < delta)); i++)
{
mp[ma++] = p[i];
}
QuickSort(mp, 0, ma - 1);
for(int i = 0 ; i < ma ; i++)
{
for(int j = i + 1 ; j < ma ; j++)
{
d3 = Distance(mp[i],mp[j]);
if(d3 < delta)
{
ret[0] = mp[i];
ret[1] = mp[j];
delta = d3;
}
}
}
return delta;
}
}
int main()
{
Point p[100010], ans[2];
double dis = 0.0;
int n;
scanf("%d",&n);
for(int i = 0 ; i < n ; i++)
{
p[i].set();
}
QuickSort(p, 0, n-1);
dis = minDistance(p, 0, n-1, ans);
if(ans[0].x + ans[0].y <= ans[1].x + ans[1].y)
{
ans[0].print();ans[1].print();
}
else
{
ans[1].print();ans[0].print();
}
printf("miniDist=%.3f",dis);
return 0;
}