跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
编程语言java算法

华为 OD 机试:快递站点投递路径分析与解法

针对华为 OD 机试中的快递投递问题,核心在于构建站点与道路的图模型。通过遍历算法判断包裹在特定检查站限制下的可达性。解析输入输出规范,提供基于广度优先搜索的通用解法思路及代码实现,帮助理解图论在物流场景中的应用。重点涵盖节点映射、路径查找及结果排序等关键步骤。

机器人发布于 2026/2/24更新于 2026/6/1621 浏览
华为 OD 机试:快递站点投递路径分析与解法

快递投放问题解析

在华为 OD 机试的双机位 C 卷中,这类图论结合业务场景的题目非常典型。核心在于如何根据给定的道路网络和检查站限制,判断包裹能否从起点到达终点。

题目理解

我们需要处理 N 个站点和 M 个包裹的投递任务。站点之间通过道路连接,但某些路段设有检查站,会拦截特定类型的货物。我们的目标是找出所有无法完成投递的包裹编号。

输入输出规范

  • 输入:第一行包含两个整数 M 和 N(M 为包裹数,N 为道路数)。后续行描述包裹信息和道路连接。
  • 输出:无法送达的包裹列表,按升序排列;若全部可达则输出 none。

注意:实际机考中,输入格式可能因具体年份略有差异,建议以现场示例为准,重点掌握图遍历逻辑。

解题思路

这道题本质上是一个有向图的连通性问题。我们可以将站点视为节点,道路视为边。对于每个包裹,我们需要判断其起点到终点是否存在一条不被检查站阻断的路径。

算法选择

由于需要多次查询不同包裹的可达性,且数据规模通常不大(N, M <= 100),使用 BFS(广度优先搜索) 或 DFS(深度优先搜索) 即可高效解决。每次针对一个包裹进行一次图遍历,复杂度约为 O(M * (V + E)),完全在可接受范围内。

关键点

  1. 图构建:需要动态维护站点间的邻接关系。如果存在双向道路,需添加两条边。
  2. 检查站逻辑:题目中提到'检查站禁止通行',这通常意味着某些边带有属性(如禁止类型)。在代码实现时,可以将边标记为允许或禁止,遍历时跳过禁止边。
  3. 结果排序:输出前务必对无法送达的包裹 ID 进行排序,这是容易丢分的细节。

代码实现

下面给出基于 Java 的实现方案。为了保持代码清晰,我们采用邻接表存储图结构。

import java.util.*;

public class Main {
    // 定义边的内部类,记录目标站点和是否被检查站拦截
    static class Edge {
        int to;
        boolean blocked;
        public Edge(int to, boolean blocked) {
            this.to = to;
            this.blocked = blocked;
        }
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        if (!scanner.hasNextInt()) return;
        
        int m = scanner.nextInt(); // 包裹数量
        int n = scanner.nextInt(); // 道路数量
        
        // 存储包裹信息:索引对应包裹 ID,值为 {起点,终点}
        List<Package> packages = new ArrayList<>();
        for (int i = 0; i < m; i++) {
            String pkgName = scanner.next();
            String startNode = scanner.next();
            String endNode = scanner.next();
            packages.add(new Package(pkgName, startNode, endNode));
        }
        
        // 构建图:使用 Map 映射站点名称到 ID,方便处理字符串节点
        Map<String, Integer> nodeMap = new HashMap<>();
        List<List<Edge>> graph = new ArrayList<>();
        
        // 读取道路信息并建图
        // 假设道路输入格式为:起点 终点 是否拦截
        for (int i = 0; i < n; i++) {
            String u = scanner.next();
            String v = scanner.next();
            boolean isBlocked = scanner.nextBoolean(); // 假设输入包含拦截状态
            
            if (!nodeMap.containsKey(u)) nodeMap.put(u, nodeMap.size());
            if (!nodeMap.containsKey(v)) nodeMap.put(v, nodeMap.size());
            
            int uIdx = nodeMap.get(u);
            int vIdx = nodeMap.get(v);
            
            while (graph.size() <= Math.max(uIdx, vIdx)) graph.add(new ArrayList<>());
            
            graph.get(uIdx).add(new Edge(vIdx, isBlocked));
            graph.get(vIdx).add(new Edge(uIdx, isBlocked)); // 假设双向
        }
        
        List<String> failedPackages = new ArrayList<>();
        
        // 对每个包裹进行 BFS 检查
        for (Package pkg : packages) {
            if (!nodeMap.containsKey(pkg.start) || !nodeMap.containsKey(pkg.end)) {
                failedPackages.add(pkg.name);
                continue;
            }
            
            if (!bfs(nodeMap.get(pkg.start), nodeMap.get(pkg.end), graph)) {
                failedPackages.add(pkg.name);
            }
        }
        
        // 排序输出
        Collections.sort(failedPackages);
        if (failedPackages.isEmpty()) {
            System.out.println("none");
        } else {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < failedPackages.size(); i++) {
                sb.append(failedPackages.get(i));
                if (i < failedPackages.size() - 1) sb.append(" ");
            }
            System.out.println(sb.toString());
        }
    }
    
    // BFS 寻找路径
    private static boolean bfs(int start, int end, List<List<Edge>> graph) {
        if (start == end) return true;
        Queue<Integer> queue = new LinkedList<>();
        Set<Integer> visited = new HashSet<>();
        
        queue.offer(start);
        visited.add(start);
        
        while (!queue.isEmpty()) {
            int curr = queue.poll();
            for (Edge edge : graph.get(curr)) {
                if (!edge.blocked && !visited.contains(edge.to)) {
                    if (edge.to == end) return true;
                    visited.add(edge.to);
                    queue.offer(edge.to);
                }
            }
        }
        return false;
    }
    
    static class Package {
        String name, start, end;
        public Package(String name, String start, String end) {
            this.name = name;
            this.start = start;
            this.end = end;
        }
    }
}

调试与优化

在实际提交过程中,有几个坑需要注意:

  1. 节点映射:题目中的站点是字符串,直接作为数组下标会越界,必须用 HashMap 做映射。
  2. 边界情况:起点等于终点的情况,或者没有道路的情况,都要单独处理。
  3. 输入解析:Scanner 在处理混合类型(String 和 Boolean)时,有时会因为换行符导致读取错误,建议统一使用 next() 读取字符串后自行转换。
  4. 性能:虽然 N 很小,但如果测试用例极多,可以考虑预处理连通分量(Union-Find),不过对于单次查询 BFS 已经足够。

这类题目考察的是基础的数据结构应用能力。只要把图模型建对,剩下的就是标准的模板代码了。多做几道类似的图论题,手感自然就来了。

目录

  1. 快递投放问题解析
  2. 题目理解
  3. 输入输出规范
  4. 解题思路
  5. 算法选择
  6. 关键点
  7. 代码实现
  8. 调试与优化
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 华为 OD 机试:快递投放问题 (多语言解法)
  • 支持 ChatGLM/文心一言的 API 管理镜像部署手册
  • 快递投放问题:多语言算法题解
  • 华为 OD 机试双机位 C 卷 - 快递投放问题
  • C# 技术栈下 WebAPI 数据协议实战:RESTful 与 GraphQL 对比
  • 机器人活动区域算法题解
  • OD 机试真题:机器人活动区域
  • 微信小程序虚拟支付接入与 ThinkPHP 核心实现
  • 华为 OD 机试真题:机器人活动区域
  • 机器人活动区域:网格连通性算法解析
  • FLASH 坏块监测系统算法题解
  • STM32 单片机驱动 OV7725/OV2640 摄像头颜色识别检测
  • FLASH 坏块监测系统算法题解
  • Qwen Code 与 OpenSpec 实战指南:AI 驱动开发安装与落地
  • FLASH 坏块监测系统算法解析与多语言实现
  • 风险投资计划(华为 OD 算法题)
  • 斯坦福 2025 AI Index Report 核心洞察与趋势分析
  • FPGA 数字运算与控制:浮点数实现与 PID 算法
  • 华为 OD 机试真题:采购订单生成规则解析
  • 华为 OD 机试真题:部门人力分配

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online