二进制矩阵中的最短畅通路径 | 豆包MarsCode AI刷题

79 阅读3分钟

问题描述

小R最近在玩一个迷宫游戏,游戏的目标是在一个 n x n 的二进制矩阵 grid 中找到一条从左上角 (0, 0) 到右下角 (n - 1, n - 1) 的畅通路径。畅通路径必须满足以下条件:

  1. 路径经过的所有单元格的值都是 0
  2. 路径中相邻的单元格必须在 8 个方向之一上连通(相邻单元格之间共享一条边或一个角)。

你需要帮助小R找到最短的畅通路径长度。如果不存在这样的路径,返回 -1

详见:www.marscode.cn/practice/on…

解题思路

我们需要在一个 n x n 的二进制矩阵 grid 中找到一条从左上角 (0, 0) 到右下角 (n - 1, n - 1) 的最短畅通路径。畅通路径必须满足以下条件:

  1. 路径经过的所有单元格的值都是 0
  2. 路径中相邻的单元格必须在 8 个方向之一上连通(相邻单元格之间共享一条边或一个角)。

算法步骤

  1. 初始化 BFS 队列:我们需要一个队列来存储当前正在处理的单元格及其路径长度。队列的初始元素是起始点 (0, 0) 和路径长度 1

  2. 处理边界条件:如果起始点 (0, 0) 或目标点 (n-1, n-1) 是障碍(即值为 1),则直接返回 -1

  3. 定义移动方向:由于路径可以在 8 个方向上移动,我们需要定义一个包含所有可能移动方向的列表。

  4. BFS 主循环

    • 从队列中取出当前单元格。
    • 检查是否到达目标点 (n-1, n-1),如果是则返回当前路径长度。
    • 否则,将当前单元格标记为已访问(例如,将其值设为 1),并将其所有未访问的相邻单元格加入队列。
  5. 处理无解情况:如果 BFS 队列为空且未找到路径,则返回 -1

代码

from collections import deque

def solution(grid: list) -> int:
    n = len(grid)
    
    # 处理边界条件
    if grid[0][0] == 1 or grid[n-1][n-1] == 1:
        return -1
    
    # 定义8个方向的移动
    directions = [(-1, 0), (1, 0), (0, -1), (0, 1), (-1, -1), (-1, 1), (1, -1), (1, 1)]
    
    # 初始化BFS队列
    queue = deque([(0, 0, 1)])  # (row, col, path_length)
    grid[0][0] = 1  # 标记起始点为已访问
    
    while queue:
        row, col, path_length = queue.popleft()
        
        # 检查是否到达目标点
        if row == n-1 and col == n-1:
            return path_length
        
        # 探索所有8个方向
        for dr, dc in directions:
            new_row, new_col = row + dr, col + dc
            
            # 检查新位置是否在网格内且未访问
            if 0 <= new_row < n and 0 <= new_col < n and grid[new_row][new_col] == 0:
                queue.append((new_row, new_col, path_length + 1))
                grid[new_row][new_col] = 1  # 标记为已访问
    
    # 如果BFS结束仍未找到路径,返回-1
    return -1

if __name__ == '__main__':
    print(solution(grid=[[0, 1], [1, 0]]) == 2)
    print(solution(grid=[[0, 0, 0], [1, 1, 0], [1, 1, 0]]) == 4)
    print(solution(grid=[[1, 0, 0], [1, 1, 0], [1, 1, 0]]) == -1)