一、问题描述
设一组点 ,其中每个 点由其坐标 标识,并且它们的顺序是 。
目标是找到: where:
二、蛮力法求解
解决问题的基本算法是遍历每对点并保持找到的最小距离 S。 最后,将返回找到的最小距离。
伪代码:
ALGORITHM S = BASIC (C = {p₁, p₂,…, pn}: Set of points)
S = Infinity
For each i from 1 to n-1:
For each j from i + 1 to n:
If (d (pi, pj) <S)
S = d (pi, pj)
End-If
End-For
End-For
Return S
三、分治法求解
算法设计:
1. 将问题划分为子问题:
-原始问题 P = C 被分成 k = 2 个子问题 P1、P2,分别求解,从而产生 P1 的解 S1 和 P2 的 S2。--问题 P 被分成两半, 假设 c 是集合 C 中的中心点,我们创建问题 P1 = {p1, p2,..., pc-1} 和问题P2 = {pc, pc + 1,..., pn }。因此, | P1 | 和 | P2 | 的大小大致相同,问题C与原问题P具有相同的性质,它们是独立的,可以单独解决。 由于点是按 X 坐标排序的,我们可以将 P1 称为“左侧部分”,将 P2 称为“右侧部分”。
2. 基本情况的存在:
-当集合中的点数为 | P | <= 3 时,我们将停止除法。 在这种情况下,我们用基本算法解决。
3.合并子问题:
-S1 是子问题 P1 的点的最小距离,S2 是子问题 P2 的点的最小距离。 将 P1 的解 S1 和 P2 的 S2 结合起来,我们可以认为 S = min {S1, S2}。 但是,还需要考虑最近的点是 P1 中的一个,P2 中的另一个。 因此,我们将选择 P1 的 X 坐标中距离中心为 min {S1, S2} 的点,以及 P2 在其 X 坐标系中距离中心为 min {S1, S2} 的点。 X 坐标,将左侧选中的点与右侧选中的点进行比较。
伪代码:
ALGORITHM S = DC (C: Set of points ordered by their x coordinate)
if |C| <= 3 then:
Return S = BASIC (C)
else:
p_c ← Center point of C
P1 ← Points of C to p_c (not included)
P2 ← Points of C from p_c to n
S1 ← DC (P1)
S2 ← DC (P2)
S ← COMBINE (p_c, P1, S1, P2, S2)
Return S
End-if
ALGORITHM S = COMBINE (p_c: Central point of the p
P1: Subproblem of P (left part)
S1: Solution of P1,
P2: Subproblem of P (right part)
S2: Solution of P2):
PARTIAL = min {S1, S2}
S = PARTIAL
left←index the point of P1 farthest from p_c with d_x (p_left, pc) <= PARTIAL
right←index the point of P2 farthest from p_c with d_x (p_right, pc) <= PARTIAL
For each point p_i in P1 with i> = left:
For each point p_j in P2 with j <= right:
If d(p_i, p_j) < S:
S = d(p_i, p_j)
End-If
End-For
End-For
Return S
四、实验代码(部分代码)
// 表示二维点的结构
typedef struct {
float x, y;
} Point;
//
// BASIC SOLUTION
//
/*
Basic algorithm: 将所有点相互比较。结果返回点数
*/
float BASICO(const Point *cPoints, const int first, const int last) {
float S = -1; // 最近点的距离。初始化为 -1 表示无穷大
float dist; // 当前点的距离
for (int i = first; i < last; i++) {
for (int j = i+1; j < last; j++) {
// 计算 cPoints [i] 和 cPoints [j] 之间的距离
dist = distance(cPoints[i], cPoints[j]);
if (S == -1 || dist < S) {
S= dist; // 更新最近的点
}
}
}
// 返回结果
return S;
}
//
// DC SOLUTION
//
float Merge(const Point *cPoints, const int first, const int center, const int last, const float S1, const float S2) {
const float partial= (S1 < S2)? S1:S2;
int centerLeft, centerRight; // 合并的中心位置
float distAux; // 比较的点的距离
float S; // 返回的结果
S= partial; // 初始化结果
// 合并中央部分
// 搜索问题 P1 在最右边的点(左边部分)
centerLeft = center;
distAux = 0;
do {
centerLeft--;
if (centerLeft >= first) {
distAux= distanceX(cPoints[center], cPoints[centerLeft]);
}
} while (centerLeft > first && distAux < partial);
// 搜索问题 P2 在最左边的点(右边部分)
centerRight = center-1;
distAux= 0;
do {
centerRight++;
if (centerRight < last) {
distAux= distanceX(cPoints[center], cPoints[centerRight]);
}
} while (centerRight < last && distAux < partial);
if (centerRight < last) centerRight++;
// 在中央部分找到最小距离
for (int i = centerLeft; i < center; i++) {
for (int j = center; j < centerRight; j++) {
distAux = distance(cPoints[i], cPoints[j]);
if (S > distAux){
S = distAux;
}
}
}
return S;
}
/*
algorithm DC: 将所有的点分为 2
*/
float DC(const Point *cPoints, const int first, const int last) {
int center;
float S1, S2, S;
// 基本情况检查:数据包含 2 或 3 个点
if (last - first <= 3) {
S = BASIC(cPoints, first, last);
} else {
center = (first + last) / 2;
S1= DC(cPoints, first, center);
S2= DC(cPoints, center, last);
S= Merge(cPoints, first, center, last, S1, S2);
}
return S;
}
float distance(const Point pi, const Point pj) {
float dx, dy;
dx = (pi.x - pj.x)*(pi.x - pj.x);
dy = (pi.y - pj.y)*(pi.y - pj.y);
return sqrt(dx + dy);
}
float distanceX(const Point pi, const Point pj) {
float dx, dy;
dx = (pi.x - pj.x)*(pi.x - pj.x);
return sqrt(dx);
}
完整版:https://download.csdn.net/download/weixin_47154327/19835120