题目(Description):
设 p1=(x1, y1), p2=(x2, y2), …, pn=(xn, yn) 是平面上 n 个点构成的集合 S,设计分治法算法,找出集合 S 中距离最近的点对。严格地讲,最接近点对可能多于一对,简单起见,只找出其中的一对作为问题的解。
输入(Input):
点对个数n
点对坐标(x, y)
输出(Output):
最近对的距离(小数点后面保留6位)
示例(Sample):
输入(Input):
6
2 2
2.1 2.1
3.5 6
6 10
1.3 9.2
2 5
输出(Output):
0.141421
思路1
采用蛮力法
算法实现1
double ClosestPoints(Point S[], int n) { // 蛮力法求解
int i, j;
double d, minDist = DBL_MAX;
for(i=0; i<n; i++) {
for(j=i+1; j<n; j++) {
d = Distance(S[i],S[j]);
if(d < minDist) {
minDist = d;
}
}
}
return minDist;
}
测试1
int main()
{
int n; //点的数量
cin >> n;
Point S[N];
for(int i=0; i<n; i++)
cin >> S[i].x >> S[i].y;
cout << ClosestPoints(S,n);
return 0;
}
6
2 2
2.1 2.1
3.5 6
6 10
1.3 9.2
2 5
0.141421
--------------------------------
思路2
采用分治法
算法实现2
double ClosestPoints(Point S[], int low, int high) { //分治法
double d, d1, d2, d3;
int mid, i, j, index;
Point P[N]; // 存放P1 P2
if(high-low == 1) { // 只有两个点
return Distance(S[low], S[high]);
}
if(high-low == 2) { // 只有三个点
d1 = Distance(S[low], S[low+1]);
d2 = Distance(S[low+1], S[high]);
d3 = Distance(S[low], S[high]);
if((d1<d2) && (d1<d3))
return d1;
else if (d2<d3) return d2;
else return d3;
}
mid = (low+high)/2; //计算中间点
d1 = ClosestPoints(S,low,mid); //递归求解子问题1
d2 = ClosestPoints(S,mid+1,high); //递归求解子问题2
//下面处理子问题3
d = d1>d2?d2:d1; //先合并子问题1和2的解
index=0;
for(i=mid; (i>=low)&&(S[mid].x<S[i].x); i--)
P[index++] = S[i];
for(i=mid+1; (i<=high)&&(S[mid].x)>S[i].x; i++)
P[index++] = S[i];
sort(P,P+index,cmpy); //按照y升序排列
for(i=0; i<index; i++) {
for(j=i+1; j<index; j++) {
if(P[j].y-P[i].y >= d) //这些点不在矩形区域内 不需要考虑
break;
else { // 可疑点 需要计算距离 并更新子问题3的解d3
d3 = Distance(P[i],P[j]);
if(d3<d) d=d3; // 合并解
}
}
}
return d;
}
测试2
int main()
{
int n; //点的数量
cin >> n;
Point S[N];
for(int i=0; i<n; i++)
cin >> S[i].x >> S[i].y;
cout << ClosestPoints(S,0,n);
return 0;
}
6
2 2
2.1 2.1
3.5 6
6 10
1.3 9.2
2 5
0.141421
--------------------------------
注:前缀代码
#include <iostream>
#include <cmath>
#include <float.h>
#include <algorithm>
using namespace std;
#define N 10
typedef struct point {
double x, y;
}Point;
bool cmpx(Point a, Point b) {
return a.x < b.x;
}
bool cmpy(Point a, Point b) {
return a.y < b.y;
}
double Distance(Point a, Point b) {
return sqrt( (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
}