最近对问题EfficientClosetPair(P,Q)
1.问题
令P为笛卡几平面上n>1个点构成的集合,假设每个点都不一样,给定每个点的坐标,找出最近两个点的距离。
2.解析
输入:输入n>=2个点的坐标,按x轴坐标升序排序,得到数组P;按Y轴坐标升序排序,得到数组Q
输出:最近点对之间俺的欧几里得距离
if n<=3:
- 蛮力算法:
枚举两个点对,得到最小距离的点对,时间复杂度为O(N^2)
else:
-
分治求解法
- divide:
将n个元素从中间n/2分开,分为[left,n/2]和[n/2+1,right] - merge:
将P中的前[n/2]个点复制到Pl
将Q中的前[n/2]个点复制到Ql
将P中的后[n/2]个点复制到Pr
将Q中的后[n/2]个点复制到Qr
dl=EfficientClosestPair(Pl,Ql)
dr=EfficientClosestPair(Pr,Qr)
d=min{dl,dr}
通过递归分解求治dl,dr得到最短距离
还有一种情况:距离最近的两个点分别位于分界线的两侧。
设S是来自Q,位于分割线2d宽度范围内的垂直带的点的列表(其他点对的距离都至少为d),因Q的特点,S是按纵坐标升序排列的。扫描S,当遇到小于d(min)时,更新。
m=P[n/2-1].x
将Q中所有[x-m]<d的点复制到数组S[0,num-1]
dminsq=d^2
for i=0 to num-2 do
k=i+1
while k<=num-1&&(S[k].y-S[i].y)^2<dminsq
dminsq=min((S[k].x-S[i].x)^2+
(S[k].y-S[i].y)^2,dminsq)
k=k+1
retuen sqrt(dminsq)
- divide:
3.设计
在这里插入代码片```
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
typedef struct point {
double x;
double y;
} point;
int cx(const void *_a, const void *_b) {
point *a = (point*)_a;
point *b = (point*)_b;
return a->x - b->x;
}
int cy(const void *_a, const void *_b) {
point *a = (point*)_a;
point *b = (point*)_b;
return a->y - b->y;
}
double distant(point i, point j) {
return sqrt(pow(i.x - j.x, 2) + pow(j.y - i.y, 2));
}
double piar(point *points, int start, int end) {
double d = INT_MAX;
if (start == end) {
return d;
}
if (start + 1 == end) {
return distant(points[start], points[end]);
}
int mid = (start + end) / 2;
double d1 = piar(points, start, mid);
double d2 = piar(points, mid + 1, end);
d = fmin(d1, d2);
point temp[end - start + 1];
int top = 0;
for (int i = start; i <= end; ++i) {
if (abs(points[i].x - points[mid].x) < d) {
temp[top++] = points[i];
}
}
qsort(temp, top, sizeof(point), cy);
for (int i = 0; i < top - 1; ++i) {
for (int j = i + 1; j < top; ++j) {
if (abs(points[i].y - points[j].y) < d) {
double d3 = distant(points[i], points[j]);
if (d3 < d) {
d = d3;
}
}
}
}
return d;
}
int main() {
int n;
printf("请输入点的数量:");
scanf("%d", &n);
point points[n];
for (int i = 0; i < n; ++i) {
printf("请输入x和y坐标: ");
scanf("%lf%lf", &points[i].x,&points[i].y);
}
qsort(points, n, sizeof(point), cx);
printf("最小的距离为: %.2f", piar(points, 0, n - 1));
return 0;
}
/*
5
0 0
0 1
0 3
9 1
9 8
*/
4.分析
- 合并的复杂度O(n),分治递归的复杂度O(n/2)
- 总时间复杂度O(nlogn)