📜  门|门 CS 1996 |问题 4(1)

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

门 | 门 CS 1996 | 问题 4

简介

这是一个算法问题,出自 1996 年清华大学计算机科学与技术专业的《计算机科学》考试中。问题需要求解的是,在一个由若干个门组成的迷宫中,从一个门到另一个门的最短路径长度。

问题描述

假设迷宫是一个 $n$ 行 $m$ 列的矩阵,其中门用 $1$ 表示,空地用 $0$ 表示。给定两个不同的门的坐标 $(x_1, y_1)$ 和 $(x_2, y_2)$,请计算从第一个门到第二个门的最短路径长度。

输入格式

第一行包含三个整数 $n,m,q$,表示迷宫的大小以及询问数量。

接下来 $n$ 行,每行 $m$ 个整数,用空格隔开,表示迷宫。其中 $0$ 表示空地,$1$ 表示门。

接下来 $q$ 行,每行包含 $4$ 个整数 $x_1,y_1,x_2,y_2$,表示一组询问。

输出格式

对于每一个询问,输出一个整数,表示从第一个门到第二个门的最短路径长度,如果不存在合法的路径,则输出 $-1$。

解题思路

本题可以使用广度优先搜索 (BFS) 求解,具体思路如下:

  1. 首先对迷宫顶点进行编号,方便存储和查找。

  2. 对每一组询问,都进行一次 BFS,求出从起点到终点的最短路径长度。

具体实现中,可以使用一个队列来存储待遍历的顶点,同时记录每个顶点的层数,用一个数组来存储已经访问过的顶点,避免重复访问。

代码实现

下面给出一个简单的 Python 实现,时间复杂度为 $O(qmn)$。在实现中,为了代码简洁,省略了一些异常处理和边界判断。

from collections import deque

# 迷宫顶点编号
def vertex(x, y):
    return x * m + y

# BFS 搜索
def bfs(s, t):
    q = deque([(s, 0)])
    visited[s] = True
    while q:
        v, d = q.popleft()
        x, y = divmod(v, m)
        if v == t:
            return d
        for dx, dy in [(0, 1), (0, -1), (1, 0), (-1, 0)]:
            nx, ny = x + dx, y + dy
            if 0 <= nx < n and 0 <= ny < m and not visited[vertex(nx, ny)] and maze[nx][ny] == 0:
                visited[vertex(nx, ny)] = True
                q.append((vertex(nx, ny), d + 1))
    return -1

n, m, q = map(int, input().split())
maze = [list(map(int, input().split())) for i in range(n)]

for i in range(q):
    x1, y1, x2, y2 = map(int, input().split())
    s, t = vertex(x1-1, y1-1), vertex(x2-1, y2-1)
    visited = [False] * (n*m)
    print(bfs(s, t))
总结

本题考察了对 BFS 搜索算法的理解和应用,同时也需要一定的编程基础。对于初学者来说,可以通过更简单的问题逐步深入学习。对于有一定编程经验的同学,这道题也是一个不错的练习题目。