首页 > 编程语言 >快递员的烦恼【华为OD机试JAVA&Python&C++&JS题解】

快递员的烦恼【华为OD机试JAVA&Python&C++&JS题解】

时间:2024-03-30 12:34:00浏览次数:27  
标签:distance JAVA Python 题解 路径 距离 投递 int 客户

一. 题目-快递员的烦恼

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

  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手中,接下来直接走客户1到客户2之间的直通线路,最后走投递站和客户2之间的路,回到投递站,距离为1000 + 300 + 1200 =2500

路径2:快递员先把快递送到客户1手中,接下来回到快递站,再出发把客户2的快递送过去,再回到投递站,距离为1000 + 1000 + 1200 + 1200 = 4400

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

其他路径……

所有路径中,最短路径距离为2500

示例2

输入:5 1

5 1000

9 1200

17 300

132 700

500 2300

5 9 400

输出:9200

说明:在所有可行的路径中,最短路径长度为1000 + 400 + 1200 + 300 + 300 + 700 + 700 + 2300 + 2300 = 9200

二.解题思路

当解决这个问题时,我们可以按照以下步骤进行:

  1. 构建图(Graph): 将问题抽象为一个图,其中节点表示客户和投递站,边表示客户之间或客户与投递站之间的距离。这里采用邻接表的方式表示图,其中每个节点有一个列表,记录与其相连的节点和对应的距离。

  2. 计算最短路径: 使用最短路径算法,比如Dijkstra算法,计算从投递站到每个客户的最短路径。这一步旨在找到每个客户到投递站的最短距离。

  3. 遍历可能的路径: 对于每个客户,我们考虑以该客户为起点,通过其他客户形成路径。在此过程中,我们要确保所有客户都被访问到。可以使用深度优先搜索(DFS)或回溯法来尝试不同的路径组合。

  4. 计算路径长度: 对于每一种可能的路径,计算其总长度,包括从投递站到第一个客户,以及客户之间的距离。在每个客户之间可以使用已经计算好的最短路径。

  5. 找到最短路径: 在所有可能的路径中,找到总长度最短的一条路径。

  6. 输出结果: 输出最短路径的总长度。

通过这个思路,我们可以有效地解决问题,并找到最短路径的距离。

三.题解代码

Python题解代码

from sre_parse import State
n, m = [int(i) for i in input().split()]
 
dis = [[None] * (n + 1) for i in range(n + 1)]
mapping = {}
 
for i in range(n):
  uid, d = [int(j) for j in input().split()]
  mapping[uid] = i + 1
  dis[0][i + 1] = dis[i + 1][0] = d
 
for i in range(m):
  x, y, d = [int(j) for j in input().split()]
  x = mapping[x]
  y = mapping[y]
  dis[x][y] = dis[y][x] = d
 
f = [[None] * (n + 1) for i in range(1 << n)]
q = [[0, 0, 0]]
f[0][0] = 0
 
head, tail = 0, 1
while head < tail:
  now_state, now, now_d = q[head]
  head += 1
  for nxt in range(n + 1):
    if nxt != now and dis[now][nxt] is not None:
      if nxt == 0:
        nxt_state = now_state
   else:
     nxt_state = now_state | (1 << (nxt - 1))
 
    if f[nxt_state][nxt] is None or f[nxt_state][nxt] > f[now_state][now] + dis[now][nxt]:
     f[nxt_state][nxt] = f[now_state][now] + dis[now][nxt]
     q.append([nxt_state, nxt, f[nxt_state][nxt]])
     tail += 1
 
print(f[-1][0])

JAVA题解代码

import java.util.Scanner;
import java.util.*;
import java.util.stream.Stream;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
 
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int[] nums = split(in.nextLine(), " ");
        int n = nums[0];
        int r = nums[1];
        int[][] matrix = new int[n + 1][n + 1];
        for  (int i = 0; i < n+1; i++) {
            for  (int j = 0; j < n+1; j++) {
                matrix[i][j] = Integer.MAX_VALUE;
            }
        }
        int[] distiance_map = new int[2000];
        for (int i = 0; i < n; i++) {
            int[] nums1 = split(in.nextLine(), " ");
            distiance_map[nums1[0]] = i + 1;
            matrix[0][i + 1] = nums1[1];
            matrix[i + 1][0] = nums1[1];
        }
        for (int i = 0; i < r; i++) {
            int[] nums1 = split(in.nextLine(), " ");
            matrix[distiance_map[nums1[0]]][distiance_map[nums1[1]]] = nums1[2];
            matrix[distiance_map[nums1[1]]][distiance_map[nums1[0]]] = nums1[2];
        }
        
        int[][] cache = new int[1024][n + 1];
        for  (int i = 0; i < 1024; i++) {
            for  (int j = 0; j < n+1; j++) {
                cache[i][j] = Integer.MAX_VALUE;
            }
        }
 
        
        LinkedList<int[]> queue = new LinkedList<>();
        queue.add(new int[]{0, 0});
        cache[0][0] = 0;
        while (true){
            if(queue.isEmpty()){
                break;
            } else {
                int[] position = queue.poll();
                int i=0;
                while(true){
                    if(i>n){
                        break;
                    } else {
                        if(i==position[1] || matrix[position[1]][i] == Integer.MAX_VALUE){
                            i+=1;
                            continue;
                        }
                        int new_situation = position[0];
                        if(i > 0){
                            new_situation =  position[0] | Double.valueOf(Math.pow(2, i-1)).intValue();
                        }
                        
                        if (cache[new_situation][i] > cache[position[0]][position[1]] + matrix[position[1]][i]) {
                            cache[new_situation][i] = cache[position[0]][position[1]] + matrix[position[1]][i];
                            queue.add(new int[]{new_situation, i});
                        }
                    }
                    i+=1;
                }
 
            }
        }
        
 
        int final_distiance = cache[Double.valueOf(Math.pow(2, n)).intValue() - 1][0];
        if(final_distiance == Integer.MAX_VALUE){
            System.out.println(-1);
        } else {
            System.out.println(final_distiance);
        }
    }
 
    public static int[] split(String input_str,String chars){
        String[] tmp2 = input_str.split(chars);
        int[] results = new int[tmp2.length];
        for (int i = 0; i < tmp2.length; i++) {  
            results[i] = Integer.parseInt(tmp2[i]);
        }
        return results;
    }
}

C/C++题解代码

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
 
const int INF = 1e9;
int n, m;
vector<int> customer_distance;
vector<vector<int>> distance;
 
void floyd_warshall() {
    for (int k = 0; k < n; k++) {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                distance[i][j] = min(distance[i][j], distance[i][k] + distance[k][j]);
            }
        }
    }
}
 
int find_min_distance() {
    int min_distance = INF;
    for (int i = 0; i < n; i++) {
        int total_distance = 0;
        for (int j = 0; j < n; j++) {
            if (i != j) {
                total_distance += distance[i][j];
            }
        }
        min_distance = min(min_distance, total_distance);
    }
    return min_distance;
}
 
int main() {
    cin >> n >> m;
    customer_distance.resize(n);
    distance.resize(n, vector<int>(n, INF));
    for (int i = 0; i < n; i++) {
        cin >> customer_distance[i];
        distance[i][i] = 0;
    }
    for (int i = 0; i < m; i++) {
        int id1, id2, d;
        cin >> id1 >> id2 >> d;
        distance[id1 - 1][id2 - 1] = d;
        distance[id2 - 1][id1 - 1] = d;
    }
    floyd_warshall();
    cout << find_min_distance() << endl;
    return 0;
}

JS题解代码

const readline = require('readline');
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

function solve() {
    let idx = 0;
    const inf = 1e9;
    const g = [];
    const mapp = new Map();

    const get = (x) => {
        if (mapp.has(x)) {
            return mapp.get(x);
        }
        return mapp.set(x, ++idx).get(x);
    };

    rl.question('', (line) => {
        const [n, m] = line.split(' ').map(Number);

        for (let i = 0; i <= n; ++i) {
            g.push(new Array(n + 1).fill(inf));
        }

        rl.question('', (line) => {
            const values = line.split(' ').map(Number);
            for (let i = 1; i <= n; ++i) {
                const x = get(values[i - 1]);
                rl.question('', (line) => {
                    g[0][x] = g[x][0] = parseInt(line);
                });
            }

            for (let i = 0; i < m; ++i) {
                rl.question('', (line) => {
                    const [u, v, w] = line.split(' ').map(Number);
                    const uu = get(u);
                    const vv = get(v);
                    g[uu][vv] = g[vv][uu] = w;
                });
            }

            // Floyd
            for (let i = 0; i <= n; ++i) {
                for (let j = 0; j <= n; ++j) {
                    for (let k = 0; k <= n; ++k) {
                        g[i][j] = Math.min(g[i][j], g[i][k] + g[k][j]);
                    }
                }
            }

            // DP with bitmasking, initialize to infinity representing unreachable
            const f = new Array(1 << (n + 1)).fill(null).map(() => new Array(n + 1).fill(inf));
            f[1][0] = 0;

            for (let i = 1; i < (1 << (n + 1)); ++i) {
                for (let j = 0; j <= n; ++j) {
                    if ((i >> j) & 1) {
                        for (let k = 0; k <= n; ++k) {
                            f[i | (1 << k)][k] = Math.min(f[i][j] + g[j][k], f[i | (1 << k)][k]);
                        }
                    }
                }
            }

            console.log(f[(1 << (n + 1)) - 1][0]);
            rl.close();
        });
    });
}

solve();


四.代码讲解(Java&Python&C++&JS分别讲解)

Python题解代码解析:

  1. 输入处理: 从标准输入读取两个整数 n 和 m,分别表示客户数和自查找的客户之间距离信息的数量。

  2. 数组初始化: 初始化二维数组 dis 用于存储客户之间的距离,以及字典 mapping 用于映射客户id到数组索引。

  3. 读取客户信息: 通过循环读取 n 行输入,每行包含客户id和投递站到客户的距离。将客户id映射到数组索引,同时记录投递站到客户的距离。

  4. 读取自查找信息: 通过循环读取 m 行输入,每行包含两个客户id和客户之间的距离。将客户id映射到数组索引,同时记录客户之间的距离。

  5. 动态规划: 使用动态规划,初始化二维数组 f 和队列 q,其中 f 用于记录状态转移的最小距离,q 用于广度优先搜索。

  6. 状态转移: 通过状态转移更新 f 数组,表示经过某些客户的状态下,到达某个客户的最小距离。使用队列实现广度优先搜索。

  7. 输出结果: 输出 f 数组的最后一行最后一列元素,即到达所有客户并回到投递站的最小距离。

JAVA题解代码解析:

  1. 输入处理: 使用 Scanner 读取一行输入,分割得到 n 和 r。

  2. 矩阵初始化: 初始化二维矩阵 matrix,用于存储客户之间的距离。初始化距离映射数组 distance_map,用于将客户id映射到数组索引。

  3. 读取客户信息: 通过循环读取 n 行输入,每行包含客户id和投递站到客户的距离。将客户id映射到数组索引,同时记录投递站到客户的距离。

  4. 读取自查找信息: 通过循环读取 r 行输入,每行包含两个客户id和客户之间的距离。将客户id映射到数组索引,同时记录客户之间的距离。

  5. 动态规划: 使用动态规划,初始化二维数组 cache 和队列 queue,其中 cache 用于记录状态转移的最小距离,queue 用于广度优先搜索。

  6. 状态转移: 通过状态转移更新 cache 数组,表示经过某些客户的状态下,到达某个客户的最小距离。使用队列实现广度优先搜索。

  7. 输出结果: 输出 cache 数组的最后一行第一列元素,即到达所有客户并回到投递站的最小距离。

C/C++题解代码解析:

  1. 包含头文件: 包含必要的头文件,使用 C++ 的标准库。

  2. 常量和变量定义: 定义常量 INF 用于表示无穷大,以及 n、m、customer_distance 和 distance 用于存储客户和客户之间的距离。

  3. Floyd-Warshall算法: 使用 Floyd-Warshall 算法计算所有客户之间的最短路径。

  4. 计算最小距离: 遍历所有客户,计算经过不同客户的路径中最小的总距离。

  5. 输出结果: 输出最小距离。

JS题解代码解析:

  1. 使用readline模块: 使用 Node.js 的 readline 模块处理输入。

  2. 函数solve: 定义了一个 solve 函数,其中实现了输入处理、矩阵初始化、Floyd算法、DP算法等步骤。

  3. 输入处理: 通过递归调用 rl.question() 实现输入处理,获取 n、m 以及客户和客户之间的距离信息。

  4. 矩阵初始化: 初始化二维数组 g 用于存储客户之间的距离,以及 Map 对象 mapp 用于映射客户id到数组索引。

  5. Floyd算法: 使用 Floyd 算法计算所有客户之间的最短路径。

  6. DP算法: 使用DP算法和位掩码实现状态压缩,初始化数组 f,通过队列实现广度优先搜索。

  7. 输出结果: 输出最终结果,即到达所有客户并回到投递站的最小距离。

总体来说,这些代码都采用了动态规划的思想,通过计算最短路径和状态转移来求解问题。

寄语

标签:distance,JAVA,Python,题解,路径,距离,投递,int,客户
From: https://blog.csdn.net/mrdeam/article/details/137170114

相关文章

  • 园区参观路径【华为OD机试JAVA&Python&C++&JS题解】
    一.题目-园区参观路径园区某部门举办了FamilyDay,邀请员工及其家属参加;将公司园区视为一个矩形,起始园区设置在左上角,终点园区设置在右下角;家属参观园区时,只能向右和向下园区前进;求从起始园区到终点园区会有多少条不同的参观路径;输入描述:第一行为园区长和宽;后面每一行表示......
  • 1.java openCV4.x 入门-环境搭建
    专栏简介......
  • python+django在线政务便民服务系统flask
     随着时代在飞速进步,每个行业都在努力发展现在先进技术,通过这些先进的技术来提高自己的水平和优势,在线政务服务中心管理当然不能排除在外。在线政务服务中心管理系统是在实际应用和软件工程的开发原理之上,运用python语言以及vue框架进行开发。首先要进行需求分析,分析出在线政......
  • Python三级题目解析-尊老王国
    尊老王国有一个默认的规则,排队必须遵守年长的在前,年幼是在后。一支正要出城的队伍,请帮助他们顺利出城。输入:15、78、96、45、36输出:[96,78,45,36,15][3,2,4,5,1]请在划线处补全代码,实现以上功能。s=inputx=s.split( '、')a=[]b=[]n= 0fori inrange( 0......
  • python每日练(二)
    1:九九乘法表foriinrange(1,10):forjinrange(1,i+1):print("%d*%d=%d"%(i,j,i*j),end='')print()通过两个for循环嵌套使用调用乘法的因子,最后的print()是为了让输出的结果美观,因为print()自带换行的功能。1*1=12*1=22*2=43*1=33*2=63*3=9......
  • python中numpy的介绍
    介绍numpyNumPy是一个开源的Python科学计算库,它提供了一个强大的多维数组对象(例如数组和矩阵)以及用于处理这些数组的各种函数。NumPy的核心是ndarray(N-dimensionalarray)对象,它是一个快速而灵活的大数据集容器。以下是NumPy的一些主要特点和功能:1.**多维数组对象**:NumPy提......
  • [题解]P1439 【模板】最长公共子序列
    P1439【模板】最长公共子序列题意简述给出\(1,2,…,n\)的两个排列\(P_1\)和\(P_2\),求它们的最长公共子序列。范围限制:\(n\le10^5\)。样例53214512345输出:3。思路简述这道题看似是最长公共子序列,但是发现如果用\(O(n^2)\)的复杂度实现\(LCS\)就会时......
  • 【Python&GIS】Python实现批量导出面矢量要素(单个多面矢量->多个单面矢量)
    ​    可怜的我周六还在工作,已经很久没更新过博客了,今天正好有空就和大家分享一下。今天给大家带来的是使用Python将包含多个面要素/线要素的矢量批量导出单个要素的矢量,即一个要素一个矢量文件。之前写过多个矢量文件合并成一个矢量文件的博文,大家如果感兴趣可以看下:【......
  • Go 开发踩过的那些坑(适合Java转Go)
    做完事情就总结,是个好习惯。花了一个多月,将写了一年半多的Java工程迁移到Go上。来小结下学到的东西吧!一些基础map访问Javamap.get(key)ormap.getOrDefault(key,defaultValue)Goifvalue,ok:=map[key];ok{//...code}强制类型转换注意,转换为*......
  • [Java]23种设计模式
    【版权声明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权)https://www.cnblogs.com/cnb-yuchen/p/18031969出自【进步*于辰的博客】启发博文:《一次性讲清Java23种设计模式》(转发)。目录1、设计模式是什么?2、23种设计模式2.1创建型模式2.1.1单例模式最后1、设计模式是......