华为校招笔试真题 10.28 - 运输中转站计数(C++/Py/Java /Js/Go)

运输中转站计数

华为笔试真题 10月28号 第一题 100分题型

题目内容

一家物流企业共有 NNN 座中转站,各站依次标记为 111 至 NNN。站点间铺设了若干运输线路,每条线路都只支持指定方向的运输。

现已获得该网络的全部线路资料,需要回答一次运输路径计数问题。

请统计从中转站 SSS 启程、沿线路移动恰好 LLL 次后停在中转站 TTT 的路径总数。同一站点可以在途中反复到访,已经走过的线路也能够再次使用。只要经过的站点序列有一处不同,就视为两条不同路径。

输入描述

  • 首行给出两个整数 NNN、MMM,依次代表站点总数和线路总数。
  • 下一行给出三个整数 SSS、TTT、LLL,依次代表出发站、目的站和必须使用的线路条数。
  • 随后有 MMM 行,各行给出整数 uuu、vvv,说明存在一条由站点 uuu 驶向站点 vvv 的线路。
    约束:
  • 1≤N≤201 \le N \le 201≤N≤20。
  • 1≤M≤2001 \le M \le 2001≤M≤200。
  • 1≤L≤101 \le L \le 101≤L≤10。
  • 1≤u,v≤N1 \le u,v \le N1≤u,v≤N。
  • 1≤S,T≤N1 \le S,T \le N1≤S,T≤N。
  • u≠vu \ne vu=v,即线路不会连接站点自身。
  • 任意一对有序站点之间至多存在一条线路。

输出描述

输出一个整数,表示符合要求的路径总数;若没有可行路径,则输出 000。答案无需取模。

样例1

输入:

复制代码
5 7
2 5 4
2 3
3 2
3 4
4 3
3 5
2 5
5 1

输出

复制代码
2

解释:

从站点 222 启程,使用 444 条线路后停在站点 555,有以下两种走法:

  • 2→3→2→3→52 \to 3 \to 2 \to 3 \to 52→3→2→3→5。
  • 2→3→4→3→52 \to 3 \to 4 \to 3 \to 52→3→4→3→5。
    两种走法都再次到访了站点 333。

样例2

输入:

复制代码
6 6
2 6 2
2 1
1 6
2 4
4 6
2 5
5 6

输出:

复制代码
3

解释:

由站点 222 出发,使用 222 条线路到站点 666,可选择 2→1→62 \to 1 \to 62→1→6、2→4→62 \to 4 \to 62→4→6 或 2→5→62 \to 5 \to 62→5→6。

样例 3

输入:

复制代码
5 4
4 1 1
4 2
2 1
1 5
5 3

输出:

复制代码
0

解释:

站点 444 没有直接驶向站点 111 的线路,因此只使用 111 条线路无法抵达目的站。

题解和思路

思路

实现思路:动态规划

  1. 定义dp数组,其中dp[i]表示当前轮到达i的路径数量。
  2. 上一轮可以到达的站点使用pos进行保存,当前轮能够到达站点使用nextPos保存,对应状态转移为,对于pos中每个站点u存在u->v路径,可得到ndp[v] += dp[u], 并将v加入nextPos用于下一轮状态转移。
  3. 按照1、2进行L轮状态转移,最终结果为dp[t]
  4. 算法时间复杂度为O(L(n + m))

C++

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, m;
    int s,t,l;
    cin >> n >> m;
    cin >> s >> t >> l;
    vector<vector<int>> grid(n + 1);
    for (int i = 0; i < m; i++) {
        int u,v;
        cin >> u >> v;
        grid[u].push_back(v);
    }
    
    vector<int> dp(n + 1, 0);
    set<int> pos;
    dp[s] = 1;
    pos.insert(s);
    for (int i = 0; i < l; i++) {
        vector<int> ndp(n + 1, 0);
        set<int> nextPos;
        for (auto u : pos) {
            for (auto v : grid[u]) {
                ndp[v] += dp[u];
                nextPos.insert(v);
            }
        }
        dp = ndp;
        pos = nextPos;
    }
    cout << dp[t];
    return 0;
} 

Java

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

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

        int n = sc.nextInt();
        int m = sc.nextInt();
        int s = sc.nextInt();
        int t = sc.nextInt();
        int l = sc.nextInt();

        // 邻接表
        List<List<Integer>> grid = new ArrayList<>();
        for (int i = 0; i <= n; i++) {
            grid.add(new ArrayList<>());
        }

        for (int i = 0; i < m; i++) {
            int u = sc.nextInt();
            int v = sc.nextInt();
            grid.get(u).add(v);
        }

        // 当前轮到达i的路径个数
        int[] dp = new int[n + 1];
        Set<Integer> pos = new HashSet<>();
        dp[s] = 1;
        pos.add(s);

        for (int i = 0; i < l; i++) {
            int[] ndp = new int[n + 1];
            Set<Integer> nextPos = new HashSet<>();

            for (int u : pos) {
                for (int v : grid.get(u)) {
                    ndp[v] += dp[u];
                    nextPos.add(v);
                }
            }

            dp = ndp;
            pos = nextPos;
        }

        System.out.println(dp[t]);
        sc.close();
    }
}

python

python 复制代码
import sys

def main():
    input = sys.stdin.readline

    n, m = map(int, input().split())
    s, t, l = map(int, input().split())

    # 邻接表
    grid = [[] for _ in range(n + 1)]
    for _ in range(m):
        u, v = map(int, input().split())
        grid[u].append(v)

    # 当前轮到达i的路径个数
    dp = [0] * (n + 1)
    pos = {s}
    dp[s] = 1

    for _ in range(l):
        ndp = [0] * (n + 1)
        next_pos = set()

        for u in pos:
            for v in grid[u]:
                ndp[v] += dp[u]
                next_pos.add(v)

        dp = ndp
        pos = next_pos

    print(dp[t])

if __name__ == "__main__":
    main()

Javascript

js 复制代码
const readline = require('readline');

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

const input = [];

rl.on('line', line => {
    input.push(...line.trim().split(/\s+/).filter(Boolean));
});

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

    const n = Number(input[idx++]);
    const m = Number(input[idx++]);
    const s = Number(input[idx++]);
    const t = Number(input[idx++]);
    const l = Number(input[idx++]);

    // 邻接表
    const grid = Array.from({ length: n + 1 }, () => []);

    for (let i = 0; i < m; i++) {
        const u = Number(input[idx++]);
        const v = Number(input[idx++]);
        grid[u].push(v);
    }

    // 当前轮到达i的路径个数
    let dp = new Array(n + 1).fill(0);
    let pos = new Set([s]);
    dp[s] = 1;

    for (let i = 0; i < l; i++) {
        const ndp = new Array(n + 1).fill(0);
        const nextPos = new Set();

        for (const u of pos) {
            for (const v of grid[u]) {
                ndp[v] += dp[u];
                nextPos.add(v);
            }
        }

        dp = ndp;
        pos = nextPos;
    }

    console.log(dp[t]);
});

Go

go 复制代码
package main

import (
	"bufio"
	"fmt"
	"os"
)

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

	var n, m int
	var s, t, l int
	fmt.Fscan(reader, &n, &m)
	fmt.Fscan(reader, &s, &t, &l)

	// 邻接表
	grid := make([][]int, n+1)
	for i := 0; i < m; i++ {
		var u, v int
		fmt.Fscan(reader, &u, &v)
		grid[u] = append(grid[u], v)
	}

	// 当前轮到达i的路径个数
	dp := make([]int, n+1)
	pos := make(map[int]bool)
	dp[s] = 1
	pos[s] = true

	for i := 0; i < l; i++ {
		ndp := make([]int, n+1)
		nextPos := make(map[int]bool)

		for u := range pos {
			for _, v := range grid[u] {
				ndp[v] += dp[u]
				nextPos[v] = true
			}
		}

		dp = ndp
		pos = nextPos
	}

	fmt.Println(dp[t])
}
相关推荐
熊猫钓鱼>_>11 小时前
碰一碰无网近场文件快传与断点续传【鸿蒙心迹】
华为·交互·harmonyos·arkts·鸿蒙·openharmony·鸿蒙心迹
每天进步一点点km15 小时前
自用-牛客网-华为机试编程模拟题1-python
华为od·华为·面试
懿路向前16 小时前
唤醒工作台全实录(一):立项——化性起伪与三条设计原则
人工智能·华为
hhhjhl18 小时前
开源鸿蒙平台 KMP_CMP 三方库「Clikt」适配全流程
华为·开源·harmonyos
熊猫钓鱼>_>19 小时前
四种书签,一条时间线:一个读书 App 的记忆颗粒与它的边界案例【鸿蒙心迹】
开发语言·华为·ai编程·harmonyos·鸿蒙·openharmony·鸿蒙pc
Goway_Hui19 小时前
【KMP for OpenHarmony】-- 在鸿蒙工程中使用 Apollo-Kotlin
华为·kotlin·harmonyos
熊猫钓鱼>_>1 天前
鸿蒙 PC 三方库适配复盘:libfvad 1.0 —— 把 WebRTC VAD 做成能装进采集链路的静态库
服务器·开发语言·华为·harmonyos·openharmony·适配·鸿蒙pc
aqi001 天前
AI编程让鸿蒙开发电子书APP更加快捷
android·华为·harmonyos·鸿蒙·harmony
熊猫钓鱼>_>1 天前
鸿蒙PC高分屏与键鼠交互适配:DPI缩放、右键菜单一次讲清
开发语言·笔记·华为·ai编程·harmonyos·鸿蒙·鸿蒙心迹