问题描述
A 市计划新建一个火车站方便市民出行。
这里的道路十分规整,市民从位置(x1, y1)到位置(x2, y2)的路程为 |x1 - x2| + |y1 - y2| 。
经过前期考察,初步选定了M个可以建造火车站的位置。
为了尽可能节省市民到达火车站的时间,市长希望新建的车站离每位市民的总路程尽可能小。
请帮市长选出最合适新建火车站的位置。
输入格式
第一行有两个整数 N, M;分别表示市民的人数和可以建设火车站的位置
后面N行,每行 2 个整数 x_i, y_i,表示第i位市民的居住位置在 (x_i, y_i)
后面M行,每行 2 个整数p_i, q_i,表示第i个火车站候选位置在 (p_i, q_i)
输出格式
两个整数 p_i, q_i 表示最合适新建火车站的位置,若有多个答案,输出原始数据中第一个出现的
输入样例:
4 3
-1 -1
-1 1
1 -1
1 1
3 2
1 0
0 0
输出样例:
1 0
数据范围
1 <= N <= 100000
1 <= M <= 100000
-10000000 <= x_i, y_i, p_i, q_i <= 10000000
思路
贪心策略:
- 选择当前最优的火车站位置:对于每一个火车站位置,计算所有市民到该位置的总距离。
- 更新最小总距离:在所有计算的总距离中,选择最小的那个作为当前最优解。
AC代码
public class Main {
public static int[] solution(int n, int m, int[][] citizens, int[][] locations) {
int minTotalDistance = Integer.MAX_VALUE;
int[] bestLocation = new int[]{-1, -1};
for (int i = 0; i < m; i++) {
int totalDistance = 0;
for (int j = 0; j < n; j++) {
totalDistance += Math.abs(citizens[j][0] - locations[i][0]) + Math.abs(citizens[j][1] - locations[i][1]);
}
if (totalDistance < minTotalDistance) {
minTotalDistance = totalDistance;
bestLocation = locations[i];
}
}
return bestLocation;
}
public static boolean arrayEqual(int[] a, int[] b) {
if (a.length != b.length) {
return false;
}
for (int i = 0; i < a.length; i++) {
if (a[i] != b[i]) {
return false;
}
}
return true;
}
public static void main(String[] args) {
int[][] citizens1 = {{-1, -1}, {-1, 1}, {1, -1}, {1, 1}};
int[][] locations1 = {{3, 2}, {1, 0}, {0, 0}};
int[] result = solution(4, 3, citizens1, locations1);
int[] expected = {1, 0};
System.out.println(arrayEqual(result, expected));
}
}
总结
贪心算法在这个问题中非常适用,因为它能够通过每一步的最优选择,有效地找到全局最优解。通过遍历所有火车站位置并计算总距离,我们可以确保找到最合适的火车站位置。
学习心得
通过这个问题,我学习到了贪心算法在解决优化问题时的有效性。通过计算每个候选位置到所有市民的总距离,并选择最小值,我们能够找到最优解。这种方法简单直观,且在本问题中非常适用。