题目分析
本题要求从给定的候选火车站位置中选择一个,使所有市民到火车站的曼哈顿距离总和最小。曼哈顿距离的定义为:两点 (x1,y1)(x_1, y_1)(x1,y1) 和 (x2,y2)(x_2, y_2)(x2,y2) 之间的距离为 ∣x1−x2∣+∣y1−y2∣|x_1 - x_2| + |y_1 - y_2|∣x1−x2∣+∣y1−y2∣。问题的核心是找到一个候选站点,使得与所有市民位置的距离总和最小。
这是一个典型的优化问题,我们需要遍历所有候选位置,计算其距离总和并找出最优解。
解题思路
-
输入与数据范围
本题的输入包含两类点坐标:市民的位置和候选火车站的位置,分别有 NNN 和 MMM 个,且范围可以达到 100,000100,000100,000。需要在所有候选火车站中找到一个使总曼哈顿距离最小的站点。因为计算一次曼哈顿距离需要常数时间,暴力解法的时间复杂度是 O(N×M)O(N \times M)O(N×M),适合本题的数据范围。 -
暴力解法
对每个候选站点 (pi,qi)(p_i, q_i)(pi,qi),计算其到所有市民位置的总距离。然后记录总距离最小的站点作为答案。如果有多个站点的总距离相同,则输出输入中第一个出现的站点。- 曼哈顿距离的性质非常简单,因此可以直接逐个累加所有市民到站点的距离。
- 通过维护一个变量来记录当前的最小距离以及对应站点,可以在一次遍历后获得结果。
-
优化思路
虽然暴力解法已经可以解决问题,但仍有优化空间。例如,当计算某个候选站点的总距离时,如果发现当前距离已经超过当前记录的最小距离,则可以提前终止后续计算(剪枝)。
实现步骤
-
读取输入
解析市民和候选站点的坐标,分别存储在数组中。 -
暴力搜索
对每个候选站点:- 初始化当前总距离为 0。
- 遍历所有市民,计算其到该站点的曼哈顿距离并累加。
- 与当前最小距离进行比较,更新最优解。
-
返回结果
输出总距离最小的候选站点位置。
核心代码
以下是本题的 Java 实现:
java
Copy code
public class Main {
public static int[] solution(int n, int m, int[][] citizens, int[][] locations) {
long minDistance = Long.MAX_VALUE; // 当前最小总距离
int[] bestLocation = new int[2]; // 最优站点
for (int i = 0; i < m; i++) {
int px = locations[i][0];
int py = locations[i][1];
long totalDistance = 0;
for (int[] citizen : citizens) {
int cx = citizen[0];
int cy = citizen[1];
totalDistance += Math.abs(cx - px) + Math.abs(cy - py);
if (totalDistance >= minDistance) {
break; // 剪枝优化
}
}
if (totalDistance < minDistance) {
minDistance = totalDistance;
bestLocation = locations[i];
}
}
return bestLocation;
}
public static void main(String[] args) {
int[][] citizens = {{-1, -1}, {-1, 1}, {1, -1}, {1, 1}};
int[][] locations = {{3, 2}, {1, 0}, {0, 0}};
int[] result = solution(4, 3, citizens, locations);
System.out.println(result[0] + " " + result[1]); // 输出 1 0
}
}
时间复杂度分析
- 外层循环遍历 MMM 个候选站点,内层循环遍历 NNN 个市民,总时间复杂度为 O(N×M)O(N \times M)O(N×M)。对于最大范围 N,M≤100,000N, M \leq 100,000N,M≤100,000,可以在合理时间内完成。
- 剪枝优化可以减少部分不必要的计算,在某些情况下加速程序运行。
测试与边界情况
-
基本测试:包含少量市民和候选站点,验证程序功能是否正确。
-
边界测试:
- N=1N = 1N=1,M=1M = 1M=1:市民和候选站点都只有一个。
- 市民和候选站点重合。
- 所有坐标的绝对值接近最大值(例如 −107-10^7−107 和 10710^7107)。
-
性能测试:
- N,M=100,000N, M = 100,000N,M=100,000,验证程序在大输入范围下的执行效率。
总结
本题通过暴力搜索和剪枝优化,直接计算曼哈顿距离总和,解决了问题。由于问题本身具有简单的数学性质和数据范围合理,暴力方法已经足够高效。优化后的解法保证了正确性与运行效率的平衡,非常适合实际应用场景。