假设我们在p
网格上有M-by-M
个随机点。我们希望在网格上找到一个点,该点与所有p
点的曼哈顿距离之和最小。
我的想法:我认为可能平均所有x和y并且尝试接近该点的所有9个点我们可能找到所请求的点。但似乎这种方法不起作用:
static void find_center(int p , int M){
int[][] point = new int[p][2]; // initializing p points as random
Random r = new Random();
for (int i = 0 ; i < p ; i++){
point[i][0] = r.nextInt(M);
point[i][1] = r.nextInt(M);
}
//the naive brute force approach to find the real closest point on the grid
int min_distance = Integer.MAX_VALUE;
int[] result = new int[2];
for (int i = 0 ; i < M ; i++){
for (int j = 0 ; j < M ; j++){
int d = 0;
for (int k = 0 ; k < point.length ; k++){
d += Math.abs(i - point[k][0]);
d += Math.abs(j - point[k][1]);
}
if (d < min_distance){
min_distance = d;
result[0] = i;
result[1] = j;
}
}
}
System.out.println(min_distance);
System.out.println(result[0] + " : " + result[1]);
//the other proposed approach
System.out.println("---------");
int x = 0;
int y = 0;
for (int i = 0 ; i < point.length ; i++){
x += point[i][0];
y += point[i][1];
}
x /= point.length;
y /= point.length;
min_distance = Integer.MAX_VALUE;
for (int a : new int[] {-1,0,1}){
for (int b : new int[] {-1,0,1}){
int d = 0;
for (int k = 0 ; k < point.length ; k++){
d += Math.abs(x + a - point[k][0]);
d += Math.abs(y + b - point[k][1]);
}
if (d < min_distance){
min_distance = d;
result[0] = x + a;
result[1] = y + b;
}
}
}
System.out.println(min_distance);
System.out.println(result[0] + " : " + result[1]);
return;
}
答案 0 :(得分:3)
我认为你要找的点是中位数X和中位数Y:X和Y在他们之前有多少点 - 分别在X和Y维度上 - 跟在他们之后。
此时,向左或向右移动不会减少总距离,因为右边有相同数量的连接。上下Y也一样。
这是由于曼哈顿距离的某种特殊定义,实际上你可以在X和Y中单独计算曼哈顿距离总数,然后加上。
编辑:中位数很容易计算,只需列出X的所有值,对其进行排序,然后选择列表中间的值。 Y也一样。
答案 1 :(得分:0)
最小生成树可以计算到所有其他点的最短距离树。
答案 2 :(得分:0)
正如jdv-Jan de Vaan所说,以下代码有效:
Arrays.sort(point , new Comparator<int[]>(){
@Override
public int compare(int[] arg0, int[] arg1) {
return Double.compare(arg0[0], arg1[0]);
}
});
int median_x = point[point.length/2][0];
Arrays.sort(point , new Comparator<int[]>(){
@Override
public int compare(int[] arg0, int[] arg1) {
return Double.compare(arg0[1], arg1[1]);
}
});
int median_y = point[point.length/2][1];
int min_distance = 0;
for (int i = 0 ; i < point.length ; i++){
min_distance += Math.abs(point[i][0] - median_x) + Math.abs(point[i][1] - median_y);
}
System.out.println(min_distance);
System.out.println(median_x + " : " + median_y);