快递员的烦恼 - 华为OD统一考试

OD统一考试(C卷)

分值: 200分

题解: Java / Python / C++

alt

题目描述

快递公司每日早晨,给每位快递员推送需要淡到客户手中的快递以及路线信息,快递员自己又查找了一些客户与客户之间的路线距离信息,请你依据这些信息,给快递员设计一条最短路径,告诉他最短路径的距离。

  1. 不限制快递包裹送到客户手中的顺序,但必须保证都送到客户手中;

  2. 用例保证一定存在投递站到每位客户之间的路线,但不保证客户与客户之间有路线,客户位置及投递站均允许多次经过;

  3. 所有快递送完后,快递员需回到投递站;

输入描述

首行输入两个正整数n、m.

接下来n行,输入快递公司发布的客户快递信息,格式为:客户id 投递站到客户之间的距离distance

再接下来的m行,是快递员自行查找的客户与客户之间的距离信息,格式为:客户1id 客户2id distance

在每行数据中,数据与数据之间均以单个空格分割规格:

0 <=n <= 10
0 <= m <= 10
0 < 客户id <= 1000
0 < distance <= 10000

输出描述

最短路径距离,如无法找到,请输出-1

示例1

输入:
2 1
1 1000
2 1200
1 2 300

输出:
2500

说明:
快递员先把快递送到客户1手中,接下来直接走客户1到客户2之间的直通线路,最后走投递站和客户2之间的路,回到投递站,距离为1000+300+1200= 2500

示例2

输入:
5 1
5 1000
9 1200
17 300
132 700
500 2300
5 9 400

输出:
9200

题解

这道题目属于图论中的最短路径问题。题目要求找到一条路径,使得快递员从投递站出发,依次经过所有客户,最后回到投递站,使得路径的总距离最短。

首先,我们需要构建一个图,图中的节点表示投递站和所有客户,边表示它们之间的距离。由于题目中给出了客户之间的距离信息,我们可以使用 Floyd 算法来计算任意两点之间的最短距离。

接下来,我们使用动态规划来求解最短路径。定义dp[state][last]表示当前情况下已经投递的客户集合为state,上一次投递的客户为last时,已经走过的最短距离。状态转移方程为:

dp[state | (1 << last)][last] = min(dp[state | (1 << last)][last], dp[state][i] + dist[i][last])

其中,state为二进制表示的已经投递的客户集合,state | (1 << last)表示将statelast位置设置为1,last 表示上一次投递的状态。dist[i][last]表示投递的客户的最短距离。

时间复杂度

Floyd-Warshall算法的时间复杂度为O(n3),动态规划的时间复杂度为O(2n * n2),总体时间复杂度为O(n3 + 2^n * n^2)。

空间复杂度

空间复杂度主要由存储距离矩阵和动态规划数组决定,为O(n^2 + 2^n * n)。

Java

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
/**
 * @author code5bug
 */
public class Main {

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

        int n = scanner.nextInt(), m = scanner.nextInt();
        int[][] dist = new int[n + 1][n + 1];
        for (int i = 0; i < dist.length; i++) Arrays.fill(dist[i], Integer.MAX_VALUE);

        // 客户id 和索引下标的对照表
        Map<Integer, Integer> idxMap = new HashMap<>();

        // 初始化客户id 到 投递站(0) 之间的距离
        for (int idx = 1; idx <= n; idx++) {
            int cid = scanner.nextInt();
            int distance = scanner.nextInt();
            dist[0][idx] = dist[idx][0] = distance;
            idxMap.put(cid, idx);
        }

        // 初始化客户与客户之间的距离
        for (int i = 0; i < m; i++) {
            int cid1 = scanner.nextInt(), cid2 = scanner.nextInt(), distance = scanner.nextInt();
            int idx1 = idxMap.get(cid1), idx2 = idxMap.get(cid2);
            dist[idx1][idx2] = dist[idx2][idx1] = distance;
        }

        // Floyd-Warshall算法 求出所有点之间的最短距离 时间复杂度为O(n^3)
        for (int k = 0; k <= n; k++) {
            dist[k][k] = 0;  // 自己到自己的距离为0
            for (int i = 0; i <= n; i++) {
                for (int j = 0; j <= n; j++) {
                    dist[i][j] = Math.min(dist[i][j], dist[i][k] + dist[k][j]);
                }
            }
        }

        // dp[state][last] 当前情况走过的最短距离
        // state 表示已经投递的客户 (指定二进制位为1表示已经投递),last表示上一次投递的客户
        int[][] dp = new int[1 << (n + 1)][n + 1];
        for (int i = 0; i < (1 << (n + 1)); i++) Arrays.fill(dp[i], Integer.MAX_VALUE);
        dp[1][0] = 0;  // 初始状态,在投递站

        for (int state = 0; state < (1 << (n + 1)); state++) {
            for (int i = 0; i <= n; i++) {
                if ((state >> i & 1) == 1 && dp[state][i] != Integer.MAX_VALUE) {    // 如果 i 已经投递 且 可达
                    for (int last = 0; last <= n; last++) {
                        dp[state | (1 << last)][last] = Math.min(dp[state | (1 << last)][last], dp[state][i] + dist[i][last]);
                    }
                }
            }
        }

        System.out.println(dp[(1 << (n + 1)) - 1][0]);
    }
}

Python

from math import inf

n, m = map(int, input().split())
dist = [[inf] * (n + 1) for _ in range(n + 1)]

# 客户id 和索引下标的对照表
idx_map = {}

# 初始化客户id  到 投递站(0) 之间的距离
for idx in range(1, n + 1):
    cid, distance = map(int, input().split())
    dist[0][idx] = dist[idx][0] = distance
    idx_map[cid] = idx

# 初始化客户与客户之间的距离
for _ in range(m):
    cid1, cid2, distance = map(int, input().split())
    idx1, idx2 = idx_map[cid1], idx_map[cid2]
    dist[idx1][idx2] = dist[idx2][idx1] = distance

# Floyd-Warshall算法 求出所有点之间的最短距离  时间复杂度为O(n^3)
for k in range(n + 1):
    dist[k][k] = 0  # 自己到自己的距离为0
    for i in range(n + 1):
        for j in range(n + 1):
            dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j])

f = [[inf] * (n + 1) for _ in range(1 << (n + 1))]
f[1][0] = 0


# dp[state][last] 当前情况走过的最短距离
# state 表示已经投递的客户 (指定二进制位为1表示已范围),last表示上一次投递的客户
dp = [[inf] * (n + 1) for _ in range(1 << (n + 1))]
dp[1][0] = 0  # 初始状态,在投递站

for state in range(1 << (n + 1)):
    for i in range(n + 1):
        if (state >> i) & 1 and dp[state][i] != inf:    # 如果 i 已经投递 且 可达
            for last in range(n + 1):
                dp[state | (1 << last)][last] = min(dp[state | (1 << last)][last], dp[state][i] + dist[i][last])

print(dp[(1 << (n + 1)) - 1][0])

C++

#include <iostream>
#include <vector>
#include <unordered_map>
#include <algorithm>
#include <climits>

using namespace std;

int main() {
    int n, m;
    cin >> n >> m;

    vector<vector<int>> dist(n + 1, vector<int>(n + 1, INT_MAX));

    // 客户id 和索引下标的对照表
    unordered_map<int, int> idxMap;

    // 初始化客户id 到 投递站(0) 之间的距离
    for (int idx = 1; idx <= n; idx++) {
        int cid, distance;
        cin >> cid >> distance;
        dist[0][idx] = dist[idx][0] = distance;
        idxMap[cid] = idx;
    }

    // 初始化客户与客户之间的距离
    for (int i = 0; i < m; i++) {
        int cid1, cid2, distance;
        cin >> cid1 >> cid2 >> distance;
        int idx1 = idxMap[cid1], idx2 = idxMap[cid2];
        dist[idx1][idx2] = dist[idx2][idx1] = distance;
    }

    // Floyd-Warshall算法 求出所有点之间的最短距离 时间复杂度为O(n^3)
    for (int k = 0; k <= n; k++) {
        dist[k][k] = 0;  // 自己到自己的距离为0
        for (int i = 0; i <= n; i++) {
            for (int j = 0; j <= n; j++) {
                dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
            }
        }
    }

    // dp[state][last] 当前情况走过的最短距离
    // state 表示已经投递的客户 (指定二进制位为1表示已经投递),last表示上一次投递的客户
    vector<vector<int>> dp(1 << (n + 1), vector<int>(n + 1, INT_MAX));
    dp[1][0] = 0;  // 初始状态,在投递站

    for (int state = 0; state < (1 << (n + 1)); state++) {
        for (int i = 0; i <= n; i++) {
            if ((state >> i & 1) == 1 && dp[state][i] != INT_MAX) {    // 如果 i 已经投递 且 可达
                for (int last = 0; last <= n; last++) {
                    dp[state | (1 << last)][last] = min(dp[state | (1 << last)][last], dp[state][i] + dist[i][last]);
                }
            }
        }
    }

    cout << dp[(1 << (n + 1)) - 1][0] << endl;

    return 0;
}

相关练习题

题号题目难易
LeetCode 29762976. 转换字符串的最小成本 I中等

‍❤️‍华为OD机试面试交流群每日真题分享): 加V时备注“华为od加群”

🙏整理题解不易, 如果有帮助到您,请给点个赞 ‍❤️‍ 和收藏 ⭐,让更多的人看到。🙏🙏🙏

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/369879.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

怎么把物品信息图片批量生成二维码?每张图片单独生码的制作技巧

现在通过扫码来查看人员或者物品信息的方式越来越常见&#xff0c;在合适的位置放置对应的二维码内容&#xff0c;让其他人通过扫码来获取图片信息。那么如果我们将每个信息做成一张图片后&#xff0c;需要将图片生成二维码时&#xff0c;有能够批量生成二维码的方法可以快速处…

【Mysql】整理

Mysql整理与总结 整理Mysql的基本内容供回顾。 参考&#xff1a; [1]. 掘金.MySQL三大日志(binlog,redolog,undolog)详解 [2]. Javaguide.MySQL三大日志(binlog、redo log和undo log)详解

2023-12蓝桥杯STEMA考试 C++ 中高级试卷解析

蓝桥杯STEMA考试 C++ 中高级试卷(12月) 一、选择题 第一题 定义字符串 string a = "Hello C++",下列选项可以获取到字符 C 的是(B)。 A、a[7] B、a[6] C、a[5] D、a[4] 第二题 下列选项中数值与其它项不同的是( C)。 A、 B、 C、 D、 第三题 定义变量 int i =…

幻兽帕鲁服务器自动重启备份-python

幻兽帕鲁服务器自动重启备份-python 1. 前置知识点2. 目录结构3. 代码内容4. 原理解释5. 额外备注 基于python编写的服务器全自动管理工具&#xff0c;能够实现自动定时备份存档&#xff0c;以及在检测到服务器崩溃之后自动重新启动&#xff0c;并且整合了对于frp端口转发工具的…

【高质量精品】2024美赛A题22页word版成品论文+数据+多版本前三问代码及代码讲解+前四问思路模型等(后续会更新)

一定要点击文末的卡片&#xff0c;进入后&#xff0c;即可获取完整资料后续参考论文!! 整体分析:这个题目是一个典型的生态系统建模问题&#xff0c;涉及到动物种群的性比例变化、资源可用性、环境因素、生态系统相互作用等多个方面。这个题目的难点在于如何建立一个合理的数学…

关于Clone

关于Clone 一般情况下&#xff0c;如果使用clone()方法&#xff0c;则需满足以下条件。 1、对任何对象o&#xff0c;都有o.clone() ! o。换言之&#xff0c;克隆对象与原型对象不是同一个对象。 2、对任何对象o&#xff0c;都有o.clone().getClass() o.getClass()。换言之&a…

实景三维技术未来的着力点应该在哪里?

随着社会经济和文化生活的不断发展&#xff0c;公共服务和公共安全就成为政府部门和各行业各部门的一个非常重要的工作&#xff0c;提高政府以及相关部门对紧急事件的快速反应和抗风险能力&#xff0c;建设应急指挥系统为公众提供更便捷的紧急救助服务&#xff0c;已经成为社会…

【GoLang入门教程】Go语言几种标准库介绍(五)

如何解决大模型的「幻觉」问题&#xff1f; 文章目录 如何解决大模型的「幻觉」问题&#xff1f;前言几种库image库 (常见图形格式的访问及生成)关键概念和类型&#xff1a;示例 IO库示例 math库(数学库)常用的函数和常量&#xff1a;示例 总结专栏集锦写在最后 前言 上一篇&a…

计算机毕业设计 | springboot 高校新生报到系统(附源码)

1&#xff0c;绪论 1.1 开发背景 学校新生报到仅仅靠原始的手工管理&#xff0c;面对大量的新生信息&#xff0c;无法有效率地将其中的重要部分提取出来&#xff0c;并做出相应的判断和处理。学校的决策只能依据报表数据&#xff0c;在浪费大量人力、物力的同时无法做到实时监…

图像模板匹配算法(MATLAB)

模板匹配是一种用于在图像中定位和识别对象的技术。它的基本思想是: 提取图像中的一个子图像作为“模板”(template)。这个子图像通常包含我们感兴趣的目标对象。 在整个原始图像上,逐点比较模板和原始图像的相似度。相似度通常用归一化的交叉相关(Normalized Cross Correlati…

Unity | 资源热更(YooAsset AB)

目录 一、AssetBundle 1. 插件AssetBundle Browser 打AB包 &#xff08;1&#xff09;Unity&#xff08;我用的版本是2020.3.8&#xff09;导入AssetBundle Browser &#xff08;2&#xff09;设置Prefab &#xff08;3&#xff09;AssetBundleBrowser面板 2. 代码打AB包…

Unity类银河恶魔城学习记录1-9 PlayerWallSilde源代码 P36

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili Player.cs using System.Collections; using System.Collections.Generic; using Unity.VisualScripting; us…

【30秒看懂大数据】数据指标

公众号&#xff1a;知幽科技 PS:本文属专栏第24篇 简单说 数据指标是指对企业经营数据转化为可量化、可衡量、可对比、可预测的一个度量或者维度同称。 举例理解 你在小区门口开了一家馒头店。 开业第一天你算了下一共卖了50个馒头&#xff0c;一共收款100元&#xff0…

通过手写简易版RPC理解RPC原理

RPC是什么 所谓的RPC其实是为了不同主机的两个进程间通信而产生的&#xff0c;通常不同的主机之间的进程通信&#xff0c;程序编写需要考虑到网络通信的功能&#xff0c;这样程序的编写将会变得复杂。RPC就来解决这一问题的&#xff0c;一台主机上的进程对另外一台主机的进程发…

乐意购项目前端开发 #6

一、商品详情页面 代码模版 创建Detail文件夹, 然后创建index.vue文件 <script setup> import { getDetail } from "/api/goods/index"; import { ref, onMounted } from "vue"; import { useRoute } from "vue-router"; import { useCar…

2024/2/3学习记录

微信小程序 小程序中组件的分类 视图容器 view 普通视图区域&#xff0c;类似于 div 常用来实现页面的布局效果。 scroll-view 可滚动的视图区域&#xff0c;常用来实现滚动列表效果 swiper 和 swiper-item 常用 swiper 组件的常用属性 轮播图容器组件和轮播图item组件 基…

【CSS】常见样式总结

一. 溢出隐藏 1.1 单行文本溢出 .content{max-width:200px; /* 定义容器最大宽度 */overflow:hidden; /* 隐藏溢出的内容 */text-overflow:ellipsis; /* 溢出部分...表示 */white-space: nowrap; /* 确保文本在一行内显示 */ }问题&#xff1a;display:flex 和 ellipsis 冲…

Win7 Python入手教程(超简单)

前言 因为最近想学习AI&#xff0c;所以准备开始用python&#xff0c;所以为了照顾和我一样用win7且认为网上的教程难以操作的人&#xff0c;所以的算水写一篇博客。 正文 安装步骤&#xff1a; 打开python官网。&#xff08;会有一点慢&#xff0c;要耐心。&#xff09; …

回归预测 | Matlab实现CPO-CNN-LSTM-Attention冠豪猪优化卷积长短期记忆神经网络注意力机制多变量回归预测(SE注意力机制)

回归预测 | Matlab实现CPO-CNN-LSTM-Attention冠豪猪优化卷积长短期记忆神经网络注意力机制多变量回归预测&#xff08;SE注意力机制&#xff09; 目录 回归预测 | Matlab实现CPO-CNN-LSTM-Attention冠豪猪优化卷积长短期记忆神经网络注意力机制多变量回归预测&#xff08;SE注…

C#,哥伦布数(Golomb Number)的算法与源代码

1 哥伦布数&#xff08;Golomb Number&#xff09; 哥伦布数&#xff08;Golomb Number&#xff09;是一个自然数的非减量序列&#xff0c;使得n在序列中正好出现G&#xff08;n&#xff09;次。前几个15的G&#xff08;n&#xff09;值为&#xff1a;1 2 2 3 3 4 4 4 5 5 5 6…