📜  门| Sudo GATE 2021 测验 |第 53 题(1)

📅  最后修改于: 2023-12-03 15:42:20.440000             🧑  作者: Mango

Sudo GATE 2021 测验 | 第 53 题

本文将介绍 Sudo GATE 2021 测验的第 53 题,题目为“门”。

题目描述

有 $n$ 个人,每个人都有一张门的钥匙,他们需要在某个时间段内通过 $m$ 扇门。每扇门都有一个对应的钥匙,只有拥有对应钥匙的人才能通过。

每个人都有一定的速度,通过某扇门需要花费一定时间,每个人只能一个接一个地通过一扇门。

给定每个人所持有的钥匙、每扇门对应的钥匙、每个人的速度和每扇门所需时间等信息,请编写一个算法,计算所有人通过所有门所需的最短时间。

解题思路

本题是一个典型的图论问题,通过建图和最短路算法可以求解。

首先,将所有的人和门看成图中的节点,对于有钥匙可以打开某门的人和该门都在节点之间连接一条有向边,边的长度为该人在通过该门时所需的时间。

然后,将所有的人和门看成一个二分图,人和门之间都是连接在不同的二分图中的。再在人和门之间连接一条二分图的边,表示该人可以通过该门。边的长度为 $0$。

最后,求出所有节点之间的最短路即为所有人通过所有门所需的最短时间。

代码实现

本题的实现方式多种多样,以下是一种基于 Python 的实现方式:

import heapq

def dijkstra(n, e, s):
    q = [(0, s)]
    dist = [float("inf")] * n
    dist[s] = 0

    while q:
        c, u = heapq.heappop(q)
        if dist[u] < c:
            continue
        for v, w in e[u]:
            alt = c + w
            if alt < dist[v]:
                dist[v] = alt
                heapq.heappush(q, (alt, v))

    return dist

def solve(n, m, keys, doors, speeds, times):
    N = n + m + 2
    s, t = 0, N - 1

    e = [[] for _ in range(N)]

    for i, k in enumerate(keys):
        e[s].append((i+1, 0))
        for j, d in enumerate(doors):
            if k == d:
                e[i+1].append((n+j+1, times[j]*speeds[i]))

    for j, d in enumerate(doors):
        e[n+j+1].append((t, 0))

    return dijkstra(N, e, s)[t]

其中,keys 是一个 $n$ 维的数组,表示每个人所持有的钥匙编号;doors 是一个 $m$ 维的数组,表示每扇门所对应的钥匙编号;speeds 是一个 $n$ 维的数组,表示每个人通过门时的速度;times 是一个 $m$ 维的数组,表示每扇门打开所需的时间。

函数 solve 的返回值即为所有人通过所有门所需的最短时间。