1、问题
蛮力算法解决最近对问题
2、解析
- 用S中个点坐标的中位数作为分割点,则会得到一个平衡的分割点m,使得子集S1,S2中有个数大致相同的点。
- 选取垂直线x=c(中位线)来作为分割线。
- 递归地求出S1和S2中的最近对,假设D1、D2是最近距离。
- 距离最近的点,可能在线的俩边,所以,我们需要在以x=c为对称的、宽度为2D的(D为D1、D2中的最小值)的垂直带中。
- 在该范围中递归得出最近距离。
3、设计
import java.util.Scanner;
/**
* @Description 最近对问题
* @Author ZhengLing
* @Date 2021/04/12 16:08
*/
public class s2_4 {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
int x = 0, x1 = 0, x2 = 0, x3 = 0, x4 = 0;
int y = 0, y1 = 0, y2 = 0;
double dis1 = 0, dis2 = 0;
System.out.print("输入需要生成多少个随机点N:");
int n = s.nextInt();
int A[][] = new int[n][2];
int B[][] = new int[n][2];
int C[][] = new int[n][2];
int D[][] = new int[n][2];
for (int i = 0; i < n; i++) {
//生成100以内的随机数,放入横坐标
A[i][0] = (int) (Math.random() * 100) + 1;
}
for (int i = 0; i < n; i++) {
//生成100以内的随机数,放入纵坐标
A[i][1] = (int) (Math.random() * 100) + 1;
}
for (int i = 0; i < n; i++) {
System.out.println("(" + A[i][0] + "," + A[i][1] + ")");
}
int minX = (int) Double.POSITIVE_INFINITY;
int maxX = (int) Double.NEGATIVE_INFINITY;
for (int i = 0; i < A.length; i++) {
if (A[i][0] < minX) {
minX = A[i][0];
}
if (A[i][0] > maxX) {
maxX = A[i][0];
}
}
int mid = (minX + maxX) / 2;
int p = 0, t = 0;
for (int i = 0; i < n; i++) {
if (A[i][0] <= mid) {
B[p][0] = A[i][0];
B[p][1] = A[i][1];
p++;
} else {
C[t][0] = A[i][0];
C[t][1] = A[i][1];
t++;
}
}
int d1 = (int) Double.POSITIVE_INFINITY, d2 = (int) Double.POSITIVE_INFINITY;
int dx = 0, dy = 0, dz = 0;
for (int i = 0; i <= p - 2; i++) {
for (int j = i + 1; j <= p - 1; j++) {
dx = (B[j][0] - B[i][0]) * (B[j][0] - B[i][0]) + (B[j][1] - B[i][1]) * (B[j][1] - B[i][1]);
if (dx < d1) {
d1 = dx;
x1 = i;
x2 = j;
}
}
}
for (int i = 0; i <= t - 2; i++) {
for (int j = i + 1; j <= t - 1; j++) {
dy = (C[j][0] - C[i][0]) * (C[j][0] - C[i][0]) + (C[j][1] - C[i][1]) * (C[j][1] - C[i][1]);
if (dy < d2) {
d2 = dy;
x3 = i;
x4 = j;
}
}
}
System.out.println("mid=" + mid + " " + "d1=" + d1 + " " + "d2=" + d2);
if (d1 < d2) {
dz = d1;
dis1 = Math.sqrt(dz);
System.out.println("x坐标中的最小距离的俩个点为:" + A[x1][0] + "," + A[x1][1] + " " + A[x2][0] + "," + A[x2][1]);
System.out.println("最小距离为:" + dis1);
x = x1;
y = x2;
} else {
dz = d2;
dis1 = Math.sqrt(dz);
System.out.println("x坐标中的最小距离的俩个点为:" + A[x3][0] + "," + A[x3][1] + " " + A[x4][0] + "," + A[x4][1]);
System.out.println("最小距离为:" + dis1);
x = x3;
y = x4;
}
int q = 0;
for (int i = 0; i < n; i++) {
if ((mid - dis1) <= A[i][0] && A[i][0] <= (mid + dis1)) {
D[q][0] = A[i][0];
D[q][1] = A[i][1];
q++;
}
}
double mind = Double.POSITIVE_INFINITY;
double dis = 0;
for (int k = 0; k <= q - 2; k++) {
for (int j = k + 1; j <= q - 1; j++) {
dis = (D[j][0] - D[k][0]) * (D[j][0] - D[k][0]) + (D[j][1] - D[k][1]) * (D[j][1] - D[k][1]);
if (dis < mind) {
mind = dis;
y1 = k;
y2 = j;
}
}
}
dis2 = Math.sqrt(mind);
System.out.println("dis1=" + dis1 + " " + "dis2=" + dis2);
if (dis1 < dis2) {
System.out.println("最小距离为:" + dis1);
System.out.print("俩个点分别为:" + "(" + A[x][0] + "," + A[x][1] + ")");
System.out.println(" " + "(" + A[y][0] + "," + A[y][1] + ")");
} else {
System.out.println("最小距离为:" + dis2);
System.out.print("俩个点分别为:" + "(" + A[y1][0] + "," + A[y1][1] + ")");
System.out.println(" " + "(" + A[y2][0] + "," + A[y2][1] + ")");
}
}
}
4、分析
O ( n ) = n l o g 2 n O(n) = nlog2n O(n)=nlog2n
本文介绍了一种使用蛮力算法和分治策略解决最近点对问题的方法。首先,通过中位数分割点将点集分为两部分,然后递归计算左右子集中的最近点对。在以分割线为中心、宽度为最近距离的区域内搜索可能的最近点对,最终确定全局最近距离。代码实现中,通过Java生成随机点并进行计算,展示了算法的具体应用。
1240

被折叠的 条评论
为什么被折叠?



