理想火车站定位 | 豆包MarsCode AI刷题

116 阅读5分钟

理想火车站位置选择分析

问题描述

小F是A市的市长,正在计划在A市新建一个火车站以方便市民的日常出行。市区内的街道布局十分规整,形成网格状。从一个位置[x1, y1]到另一个位置[x2, y2]的距离计算方法为 |x1 - x2| + |y1 - y2|,即曼哈顿距离。

在初步考察后,市政府列出了M个可能的火车站建设点。为了使得市民到火车站的总旅行时间最短,小F希望选出一个最优位置作为火车站的地址。

请你帮助小F计算出哪一个位置最适合建设新火车站。

  • N: 市民的总人数。
  • M: 可建设火车站的备选位置数。
  • citizens: 一个列表,每个元素是一个元组 [x_i, y_i],表示第 i 位市民的居住位置。
  • locations: 一个列表,每个元素是一个元组 [p_i, q_i],表示第 i 个备选的火车站位置。

如果有多个火车站最优,那么选择第一次出现的那个。


测试样例

样例1:

输入:n = 4,m = 3,citizens = [[-1, -1], [-1, 1], [1, -1], [1, 1]],locations = [[3, 2], [1, 0], [0, 0]]
输出:[1, 0]

样例2:

输入:n = 2,m = 2,citizens = [[0, 0], [0, 4]],locations = [[0, 2], [0, 3]]
输出:[0, 2]

样例3:

输入:n = 3,m = 1,citizens = [[10, 10], [20, 20], [30, 30]],locations = [[15, 15]]
输出:[15, 15]

样例4:

输入:n = 5,m = 3,citizens = [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]],locations = [[4, 5], [6, 7], [8, 9]]
输出:[4, 5]

样例5:

输入:n = 6,m = 2,citizens = [[10, 10], [20, 20], [30, 30], [40, 40], [50, 50], [60, 60]],locations = [[35, 35], [45, 45]]
输出:[35, 35]

基本思路

我们可以使用暴力法解决此问题,即遍历所有的备选火车站位置,逐一计算每个备选位置到所有市民的总曼哈顿距离,选择总距离最小的位置。

通过如下步骤可以实现:

  1. 初始化最小总距离 minDistance 为一个极大值,初始化最佳火车站位置 bestLocationnull
  2. 对每一个候选火车站位置,计算到所有市民的曼哈顿距离之和。
  3. 如果当前位置的总距离比 minDistance 小,更新最小距离和最佳位置。
  4. 返回计算出的最佳位置。

这种方法的时间复杂度为 (O(m \times n)),其中 m 是候选火车站数量,n 是市民数量。代码实现如下:

public class Main {
    public static int[] solution(int n, int m, int[][] citizens, int[][] locations) {
        int minDistance = Integer.MAX_VALUE;
        int[] bestLocation = null;

        // 遍历所有备选位置
        for (int[] location : locations) {
            int totalDistance = 0;
            // 计算当前备选位置到所有市民位置的总曼哈顿距离
            for (int[] citizen : citizens) {
                totalDistance += manhattanDistance(citizen, location);
            }
            // 更新最小总距离及其对应的备选位置
            if (totalDistance < minDistance) {
                minDistance = totalDistance;
                bestLocation = location;
            }
        }

        return bestLocation;
    }

    // 计算两个点之间的曼哈顿距离
    private static int manhattanDistance(int[] point1, int[] point2) {
        return Math.abs(point1[0] - point2[0]) + Math.abs(point1[1] - point2[1]);
    }
}

代码分析

  1. 主方法 solution
    • 通过双重循环实现,外层循环遍历火车站位置,内层循环计算当前火车站到所有市民的距离。
    • 逐步更新最优火车站的候选位置。
  2. 辅助方法 manhattanDistance
    • 计算两个点之间的曼哈顿距离,核心在于理解它的公式。

时间复杂度分析

代码的时间复杂度是 (O(m \times n)),当市民数目和候选火车站位置较多时,性能可能会受影响。例如,如果 nm 都是上千数量级,计算量将达到百万次级别。考虑优化可以参考如下方向:

  • 预计算:对市民的坐标进行分布统计,找到“集中区域”,大致锁定候选火车站的区域范围,从而减少候选位置的数量。
  • 数学分析:通过对市民坐标的聚集情况分析,利用平均值等概念来尝试缩小计算范围。

思考与分析

曼哈顿距离的特性

曼哈顿距离适用于网格化布局的城市,因为在这种城市布局中,道路仅允许在水平和垂直方向上行驶,这与真实城市交通十分接近。这种方法在处理网格状交通布局时非常有效,因此被广泛应用在城市规划、仓储物流等领域。

为什么选择总距离最小

在实际应用中,将交通站点设立在最小化市民平均出行时间的位置,可以有效提升市民的出行效率,从而带动区域的经济活动。本文中的算法选择了总距离最小化的策略,这是均衡地提升整个市区出行便捷度的合理方式。

如何选择最佳算法

从效率角度来看,虽然暴力法能够得到正确答案,但如果数据规模变大,暴力法将不再适用。为应对大规模数据,可以考虑以下改进方法:

  1. 区间法:通过将市民坐标划分为若干个密集区,以区间中心作为备选站点,可以减少备选站点数量。
  2. 动态规划:对于较为密集且具有规律的市民分布,可以考虑动态规划,避免重复计算。
  3. 数学优化:如上所述,统计各点的均值或中位数,快速锁定中心位置。

总结

本文通过曼哈顿距离算法对城市火车站的选址问题进行了分析,得出了最优选址方案。该算法简单易实现,且能有效解决大多数中小规模问题。在实际应用中,考虑规模扩展性以及市民分布特点,可以使用更复杂的优化算法提升效率。

希望本文的分析能为类似的选址问题提供有益的参考。