2025.04.09华为机考第二题


📘题目描述:

大湾区某城市地铁线路非常密集,乘客很难一眼看出选择哪条线路乘坐更合适。为了解决这个问题,地铁公司希望你开发一个程序,帮助乘客挑选乘坐时间最短的地铁线路。地铁公司提供的数据是:各相邻站点之间的乘坐时间


🧾 输入格式:

  1. 第一行是一个整数 N,表示站点总数(3 ≤ N ≤ 20);

  2. 第二行是两个站点名(单个小写字母),表示出发站和终点站;

  3. 接下来若干行,每行是:站点1 站点2 时间,表示两个相邻站点之间的乘坐时间;

  4. 最后一行为 0000 表示输入结束;

  5. 输入保证一定有唯一解。


🎯 输出格式:

输出乘坐时间最短的线路路径以及总耗时。


🧠 解题思路:

本题可以抽象为图论中的单源最短路径问题,站点是图的节点,相邻站之间的乘坐时间是边的权重。我们可以使用经典的 Dijkstra 算法 来求解最短路径。

关键要点如下:

  • 地铁图建模成无向图

  • 使用 优先队列(小顶堆) 加速查找当前最短路径;

  • Map<String, String> 记录路径回溯信息;

  • 最后从终点往回构建最短路径并输出。


✅ Java 代码(含详细注释):

import java.util.*;

public class SubwayShortestPath {

    // 边的定义:目标站点 + 花费时间
    static class Edge {
        String to;
        int time;

        public Edge(String to, int time) {
            this.to = to;
            this.time = time;
        }
    }

    // 用于优先队列中记录当前站点和累积时间(用于排序)
    static class Node implements Comparable<Node> {
        String name;
        int cost;

        public Node(String name, int cost) {
            this.name = name;
            this.cost = cost;
        }

        @Override
        public int compareTo(Node other) {
            return Integer.compare(this.cost, other.cost); // 最短优先
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        // 1️⃣ 读取站点总数
        int n = Integer.parseInt(sc.nextLine().trim());

        // 2️⃣ 读取起点和终点
        String[] line = sc.nextLine().trim().split(" ");
        String start = line[0];
        String end = line[1];

        // 3️⃣ 构建图:邻接表
        Map<String, List<Edge>> graph = new HashMap<>();
        while (sc.hasNext()) {
            String str = sc.nextLine().trim();
            if (str.equals("0000")) break;
            String[] parts = str.split(" ");
            String from = parts[0];
            String to = parts[1];
            int time = Integer.parseInt(parts[2]);

            // 无向图(双向添加边)
            graph.putIfAbsent(from, new ArrayList<>());
            graph.putIfAbsent(to, new ArrayList<>());
            graph.get(from).add(new Edge(to, time));
            graph.get(to).add(new Edge(from, time));
        }

        // 4️⃣ Dijkstra 算法核心部分
        Map<String, Integer> dist = new HashMap<>();     // 记录最短距离
        Map<String, String> prev = new HashMap<>();      // 记录路径回溯
        PriorityQueue<Node> pq = new PriorityQueue<>();  // 小顶堆,自动找最短距离的节点

        // 初始化距离表
        for (String station : graph.keySet()) {
            dist.put(station, Integer.MAX_VALUE);
        }
        dist.put(start, 0); // 起点到自己的距离是0
        pq.offer(new Node(start, 0));

        while (!pq.isEmpty()) {
            Node current = pq.poll();
            String u = current.name;

            // 如果已经到达终点,可以提前结束
            if (u.equals(end)) break;

            // 遍历相邻节点
            for (Edge e : graph.get(u)) {
                int newDist = dist.get(u) + e.time;
                if (newDist < dist.get(e.to)) {
                    dist.put(e.to, newDist);
                    prev.put(e.to, u); // 记录前驱站点
                    pq.offer(new Node(e.to, newDist));
                }
            }
        }

        // 5️⃣ 回溯路径
        List<String> path = new LinkedList<>();
        String curr = end;
        while (curr != null) {
            path.add(0, curr);
            curr = prev.get(curr); // 从终点往前找
        }

        // 6️⃣ 输出结果
        System.out.println("最短路径: " + String.join(" -> ", path));
        System.out.println("总耗时: " + dist.get(end) + " 分钟");
    }
}

🔍 示例测试

输入:

5
a e
a b 3
a c 1
b d 2
c d 4
d e 2
0000

输出:

最短路径: a -> b -> d -> e
总耗时: 7 分钟

📌 小结

  • 适合站点较少的小图(3~20个)

  • Dijkstra 算法确保最优路径

  • 数据结构用得非常清晰:邻接表、优先队列、路径回溯图

  • 可扩展性强:如加上站点换乘、票价、时段等

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值