📜  门|门CS 2011 |问题 25(1)

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

题目描述

在一个 $n \times m$ 的网格图中,一些网格有门,其他网格没有。有一个人从某个门处出发,每秒钟可以朝上下左右四个方向走一个单位距离。当他走到有门的网格上时,就可以从那个门处继续出发。现在给定起点和终点,请问这个人能否在 $T$ 秒内到达终点。

输入格式

第一行包含 4 个整数 $n,m,T,(n \leq 100,m \leq 10,T \leq 10000)$。

接下来 $n$ 行,每行包含 $m$ 个字符,其中 '.' 表示该网格为空,'#' 表示该网格有门,'S' 表示起点,'E' 表示终点。保证一个网格上最多有一个门。

输出格式

输出为一行一个整数,如果能在 $T$ 秒内到达终点,输出 0,否则输出他可以到达的点中,到终点最短路长度的最大值。

注意事项
  • 题目数据保证起点和终点都在网格内且不同
  • 按照网格如下格式输入:
5 5 10
.S...
##.#.
.#.#.
#...#
.#E#.
题解

该问题可以用 BFS 求解。

用 $dis_{i,j}$ 表示点 $(i,j)$ 到起点的最短距离。

维护一个队列,将起点入队。

每次从队头取出一个点 $(i_0,j_0)$,

对于这个点的四个方向分别进行遍历,对于每个可以访问的点 $(i,j)$,如果 $dis_{i,j} > dis_{i_0,j_0} + 1$,则更新 $dis_{i,j}=dis_{i_0,j_0}+1$,并将这个点入队。

最后判断 $dis_{end}$ 是否小于等于 $T$,如果是,则输出 0,否则输出可以到达的点中,到终点最短路长度的最大值。

def shortestDistance(n, m, T, graph):
    from collections import deque

    # 存储矩阵中每个点到 start 的最短距离
    distance = [[float('inf')] * m for _ in range(n)]

    dx = [1, -1, 0, 0]
    dy = [0, 0, 1, -1]

    start_x = start_y = end_x = end_y = -1
    for i in range(n):
        for j in range(m):
            if graph[i][j] == 'S':
                start_x, start_y = i, j
                distance[i][j] = 0
            elif graph[i][j] == 'E':
                end_x, end_y = i, j

    q = deque([(start_x, start_y)])

    while q:
        x, y = q.popleft()
        for i in range(4):
            xx, yy = x + dx[i], y + dy[i]
            if xx < 0 or xx >= n or yy < 0 or yy >= m or graph[xx][yy] == '#':
                continue
            if distance[xx][yy] > distance[x][y] + 1:
                distance[xx][yy] = distance[x][y] + 1
                q.append((xx, yy))

    if distance[end_x][end_y] > T:
        res = 0
        for i in range(n):
            for j in range(m):
                if graph[i][j] == '#':
                    res = max(res, min(distance[i][j], T - distance[i][j]))
        return res
    else:
        return 0

其中 n, m, T 分别为网格图的长、宽和限定时间。graph 表示网格图本身, 每个网格按照题目要求,用 .#SE 表示。