华为OD机试双机位C卷 - 快递投放问题 (JAVA & Python & C++ & JS & GO)

快递投放问题

华为OD机试双机位C卷 - 华为OD上机考试双机位C卷 200分题型

华为OD机试双机位C卷真题目录点击查看: 华为OD机试双机位C卷真题题库目录|机考题库 + 算法考点详解

题目描述

有N个快递站点用字符串标识,某些站点之间有道路连接。

每个站点有一些包裹要运输,每个站点间的包裹不重复,路上有检查站会导致部分货物无法通行,计算哪些货物无法正常投递?

输入描述

  • 第一行输入M N,M个包裹N个道路信息.
  • 0<=M,N<=100,
  • 检查站禁止通行的包裹如果有多个以空格分开

输出描述

  • 输出不能送达的包裹,如:package2 package4,
  • 如果所有包裹都可以送达则输出:none,
  • 输出结果按照升序排列。

用例1

输入

none 复制代码
4 2
package1 A C
package2 A C
package3 B C
package4 A C
A B package1
A C package2

输出

none 复制代码
package2

题解

思路:BFS

  1. 这道题题目太短并且描述也不太准确,通过测试案例和题意结合来看我个人认为的意思: 给定所有包裹的起点和目标终点。然后给出n条线路,其中每条线路表示这两个站点互连,同时这条线路可以禁止某些包裹通过。
  2. 通过1的分析这道题就转换为带有限制的无向图,判断指定路径是否可达。
  3. 通过记录线路站点并且禁止包裹,循环使用BFS判断每个包裹是否能从起点到达终点,不可达的包裹加入结果数组。
  4. 如果不存在不可达包裹,输出none. 否则升序排列之后,按照空格分割输出。

c++

c++ 复制代码
#include<iostream>
#include<vector>
#include<string>
#include <utility> 
#include <sstream>
#include<algorithm> 
#include<cmath>
#include<map>
#include<unordered_set>
#include<set>
#include<queue>
using namespace std;


// 边结构
struct Edge {
    string to;                      // 目标站点
    unordered_set<string> banned;  // 禁止通过的包裹
};

// 包裹结构
struct Package {
    string name;
    string start;
    string end;
};


// 通用 切割函数 函数 将字符串str根据delimiter进行切割
vector<string> split(const string& str, const string& delimiter) {
    vector<string> result;
    size_t start = 0;
    size_t end = str.find(delimiter);
    while (end != string::npos) {
        result.push_back(str.substr(start, end - start));
        start = end + delimiter.length();
        end = str.find(delimiter, start);
    }
    // 添加最后一个部分
    result.push_back(str.substr(start));
    return result;
}


int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);    
    int m,n;
    cin >> m >> n;
    // 忽略换行符
    cin.ignore();

    vector<Package> packages(m);
    for (int i = 0; i < m; i++) {
        string input;
        getline(cin, input);
        vector<string> tmp = split(input, " ");
        packages[i].name = tmp[0];
        packages[i].start = tmp[1];
        packages[i].end = tmp[2];
    }

    // 存储每个包裹被进制的路线
    map<string, vector<Edge>> graph;
    for (int i = 0; i < n; i++) {
        string input;
        getline(cin, input);
        vector<string> tmp = split(input, " ");
        unordered_set<string> banned(tmp.begin()+2, tmp.end());
        // 无向图,双向加边
        graph[tmp[0]].push_back({tmp[1], banned});
        graph[tmp[1]].push_back({tmp[0], banned});
    }
    vector<string> res;

    // BFS判断每个包裹是否可到达
    for (auto &pkg : packages) {
        queue<string> q;
        unordered_set<string> visited;
        q.push(pkg.start);
        visited.insert(pkg.start);
        bool canReach = false;

        while (!q.empty()) {
            string cur = q.front();
            q.pop();
            if (cur == pkg.end) {
                canReach = true;
                break;
            }
            if (!graph.count(cur)) continue;
            for (auto &edge : graph[cur]) {
                 // 如果这条路禁止该包裹,跳过
                if (edge.banned.count(pkg.name)) continue;
                if (!visited.count(edge.to)) { 
                    visited.insert(edge.to);
                    q.push(edge.to);
                }
            }
        }
        if(!canReach) {
            res.push_back(pkg.name);
        }
    }


    // 都可送达
    if (res.empty()) {
        cout << "none";
        return 0;
    }
    // 升序
    sort(res.begin(), res.end());

    // 输出结果
    for (int i = 0; i < res.size(); i++) {
        if (i != 0) {
            cout << " ";
        }
        cout << res[i];
    }

    return 0;
}

JAVA

JAVA 复制代码
import java.io.*;
import java.util.*;

// 边结构
class Edge {
    String to;                    // 目标站点
    Set<String> banned;           // 禁止通过的包裹

    Edge(String to, Set<String> banned) {
        this.to = to;
        this.banned = banned;
    }
}

// 包裹结构
class PackageInfo {
    String name;
    String start;
    String end;
}

public class Main {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());

        int m = Integer.parseInt(st.nextToken());
        int n = Integer.parseInt(st.nextToken());

        List<PackageInfo> packages = new ArrayList<>();

        // 读取包裹信息
        for (int i = 0; i < m; i++) {
            st = new StringTokenizer(br.readLine());
            PackageInfo pkg = new PackageInfo();
            pkg.name = st.nextToken();
            pkg.start = st.nextToken();
            pkg.end = st.nextToken();
            packages.add(pkg);
        }

        // 图结构
        Map<String, List<Edge>> graph = new HashMap<>();

        // 读取道路信息
        for (int i = 0; i < n; i++) {
            st = new StringTokenizer(br.readLine());
            String u = st.nextToken();
            String v = st.nextToken();

            Set<String> banned = new HashSet<>();
            while (st.hasMoreTokens()) {
                banned.add(st.nextToken());
            }

            graph.computeIfAbsent(u, k -> new ArrayList<>()).add(new Edge(v, banned));
            graph.computeIfAbsent(v, k -> new ArrayList<>()).add(new Edge(u, banned));
        }

        List<String> res = new ArrayList<>();

        // BFS 判断每个包裹是否可达
        for (PackageInfo pkg : packages) {
            Queue<String> q = new LinkedList<>();
            Set<String> visited = new HashSet<>();

            q.offer(pkg.start);
            visited.add(pkg.start);
            boolean canReach = false;

            while (!q.isEmpty()) {
                String cur = q.poll();
                if (cur.equals(pkg.end)) {
                    canReach = true;
                    break;
                }
                if (!graph.containsKey(cur)) continue;

                for (Edge e : graph.get(cur)) {
                    // 该路径禁止
                    if (e.banned.contains(pkg.name)) continue;
                    if (!visited.contains(e.to)) {
                        visited.add(e.to);
                        q.offer(e.to);
                    }
                }
            }

            if (!canReach) {
                res.add(pkg.name);
            }
        }

        if (res.isEmpty()) {
            System.out.print("none");
        } else {
            Collections.sort(res);
            System.out.print(String.join(" ", res));
        }
    }
}

Python

python 复制代码
from collections import deque, defaultdict

# 读取 m, n
m, n = map(int, input().split())

# 读取包裹信息
packages = []
for _ in range(m):
    name, start, end = input().split()
    packages.append((name, start, end))

# 图结构:站点 -> [(目标站点, 禁止包裹集合)]
graph = defaultdict(list)

# 读取道路信息
for _ in range(n):
    parts = input().split()
    u, v = parts[0], parts[1]
    banned = set(parts[2:])

    graph[u].append((v, banned))
    graph[v].append((u, banned))

res = []

# BFS 判断每个包裹是否可达
for name, start, end in packages:
    q = deque([start])
    visited = {start}
    can_reach = False

    while q:
        cur = q.popleft()
        if cur == end:
            can_reach = True
            break
        if cur not in graph:
            continue
        for nxt, banned in graph[cur]:
            # 路径禁止通过
            if name in banned:
                continue
            if nxt not in visited:
                visited.add(nxt)
                q.append(nxt)

    if not can_reach:
        res.append(name)

# 输出结果
if not res:
    print("none")
else:
    res.sort()
    print(" ".join(res))

JavaScript

js 复制代码
// ACM 模式(Node.js + readline)
const readline = require('readline');

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

let lines = [];
rl.on('line', line => {
    lines.push(line.trim());
});

rl.on('close', () => {
    let idx = 0;

    // 读取 m, n
    let [m, n] = lines[idx++].split(/\s+/).map(Number);

    // 读取包裹信息
    let packages = [];
    for (let i = 0; i < m; i++) {
        let [name, start, end] = lines[idx++].split(/\s+/);
        packages.push({ name, start, end });
    }

    // 图结构
    let graph = new Map();

    // 读取道路信息
    for (let i = 0; i < n; i++) {
        let parts = lines[idx++].split(/\s+/);
        let u = parts[0], v = parts[1];
        let banned = new Set(parts.slice(2));

        if (!graph.has(u)) graph.set(u, []);
        if (!graph.has(v)) graph.set(v, []);

        graph.get(u).push({ to: v, banned });
        graph.get(v).push({ to: u, banned });
    }

    let res = [];

    // BFS 判断每个包裹是否可达
    for (let pkg of packages) {
        let queue = [pkg.start];
        let visited = new Set([pkg.start]);
        let canReach = false;

        while (queue.length > 0) {
            let cur = queue.shift();
            if (cur === pkg.end) {
                canReach = true;
                break;
            }
            if (!graph.has(cur)) continue;

            for (let edge of graph.get(cur)) {
                // 如果这条路禁止该包裹,跳过
                if (edge.banned.has(pkg.name)) continue;

                if (!visited.has(edge.to)) {
                    visited.add(edge.to);
                    queue.push(edge.to);
                }
            }
        }

        if (!canReach) {
            res.push(pkg.name);
        }
    }

    // 输出结果
    if (res.length === 0) {
        console.log("none");
    } else {
        res.sort();
        console.log(res.join(" "));
    }
});

Go

go 复制代码
package main

import (
	"bufio"
	"fmt"
	"os"
	"sort"
	"strconv"
	"strings"
)

// 边结构
type Edge struct {
	to     string
	banned map[string]bool
}

// 包裹结构
type Package struct {
	name  string
	start string
	end   string
}

func main() {
	reader := bufio.NewReader(os.Stdin)

	// 读取第一行:m n
	line, _ := reader.ReadString('\n')
	line = strings.TrimSpace(line)
	parts := strings.Fields(line)

	m, _ := strconv.Atoi(parts[0])
	n, _ := strconv.Atoi(parts[1])

	// 读取包裹信息
	packages := make([]Package, m)
	for i := 0; i < m; i++ {
		line, _ = reader.ReadString('\n')
		parts = strings.Fields(line)
		packages[i] = Package{
			name:  parts[0],
			start: parts[1],
			end:   parts[2],
		}
	}

	// 图结构
	graph := make(map[string][]Edge)

	// 读取道路信息
	for i := 0; i < n; i++ {
		line, _ = reader.ReadString('\n')
		parts = strings.Fields(line)

		u, v := parts[0], parts[1]
		banned := make(map[string]bool)
		for _, p := range parts[2:] {
			banned[p] = true
		}

		graph[u] = append(graph[u], Edge{to: v, banned: banned})
		graph[v] = append(graph[v], Edge{to: u, banned: banned})
	}

	res := []string{}

	// BFS 判断每个包裹是否可达
	for _, pkg := range packages {
		queue := []string{pkg.start}
		visited := map[string]bool{pkg.start: true}
		canReach := false

		for len(queue) > 0 {
			cur := queue[0]
			queue = queue[1:]

			if cur == pkg.end {
				canReach = true
				break
			}

			for _, e := range graph[cur] {
				// 如果这条路禁止该包裹,跳过
				if e.banned[pkg.name] {
					continue
				}
				if !visited[e.to] {
					visited[e.to] = true
					queue = append(queue, e.to)
				}
			}
		}

		if !canReach {
			res = append(res, pkg.name)
		}
	}

	// 输出结果
	if len(res) == 0 {
		fmt.Print("none")
	} else {
		sort.Strings(res)
		fmt.Print(strings.Join(res, " "))
	}
}
相关推荐
vftOWpVs1 天前
施耐德M241 PLC与IAI伺服电缸Ethernet IP通讯解决方案:PLC与伺服配套软件...
华为od
无限码力1 天前
华为OD机试双机位C卷 - 明日之星选举 (JAVA & Python & C/ C++ & JS & GO)
华为od·华为od机考·华为od机试真题·华为od机试·华为od上机考试双机位c卷·华为od上机考试真题·华为od机考真题
无限码力8 天前
华为OD技术面真题 - 计算机网络 - 3
计算机网络·华为od·面试·华为od技术面真题·华为od面试八股文·华为od技术面计算机网络相关
无限码力9 天前
华为OD技术面真题 - 计算机网络 - 2
计算机网络·华为od·华为od技术面真题·华为od面试八股文·华为od技术面计算机网络相关
无限码力9 天前
华为OD机试真题双机位C卷 【运维日志排序】C语言实现
c语言·华为od·华为od机考·华为od机试真题·华为od机试双机位c卷·华为od机考双机位c卷·华为od上机考试
嵌入式进阶行者10 天前
【算法】用三种解法解决字符串替换问题的实例:华为OD机考双机位A卷 - 密码解密
c++·算法·华为od
无限码力10 天前
华为OD技术面真题 - 计算机网络 - 1
计算机网络·华为od·华为od面试八股文·华为od面试真题
Tony_yitao11 天前
22.华为OD机试真题:数组拼接(Java实现,100分通关)
java·算法·华为od·algorithm
无限码力13 天前
华为OD机试真题 - 支持优先级队列 (C++ & Python & JAVA & JS & GO)
华为od·华为od机考·华为od机试真题·华为od机试·华为od机试双机位c卷·华为od上机考试