青训营X豆包MarsCode 技术训练营第六课 | 豆包MarsCode AI 刷题

97 阅读3分钟

最小化穿越黑色格子的迷宫路径算法解析

在最近的编程挑战中,我遇到了一个有趣的问题:帮助小S在一个n×m的网格迷宫中从左上角(1,1)移动到右下角(n,m),同时尽可能少地经过黑色格子。这个问题不仅考验了我的算法设计能力,还锻炼了我的逻辑思维和优化技巧。以下是我对这个问题的理解和解题思路。

问题描述

小S在一个n×m的网格迷宫中,初始位置在左上角(1,1),目标是到达右下角(n,m)。每个格子可以是黑色(表示为1)或者白色(表示为0)。他希望在移动过程中经过的黑色格子尽可能少。移动时可以向上、下、左、右四个方向移动,但不能走出迷宫的边界。

输入和输出

  • 输入:
    • n: 迷宫的行数。
    • m: 迷宫的列数。
    • grid: 一个n×m的二维数组,表示迷宫,其中1表示黑色格子,0表示白色格子。
  • 输出: 从起点到终点所需经过的最少黑色格子的数量。

问题介绍

我们需要在一个n×m的网格迷宫中,从左上角(1,1)移动到右下角(n,m),并且希望经过的黑色格子(值为1的格子)尽可能少。

数据结构与算法选择

  • 网格表示:使用二维数组grid来表示迷宫。
  • 访问状态:可以使用一个二维数组visited来记录每个格子是否已经被访问过。
  • 队列:使用队列来进行广度优先搜索(BFS),因为BFS可以保证找到的路径是最短路径。

算法步骤

  1. 初始化

    • 创建一个队列,并将起点(0, 0)入队。
    • 创建一个二维数组visited来记录每个格子是否已经被访问过。
    • 创建一个二维数组blackCount来记录到达每个格子时经过的最少黑色格子数量。
  2. BFS遍历

    • 从队列中取出一个格子(x, y)。
    • 检查它的四个相邻格子(x+1, y), (x-1, y), (x, y+1), (x, y-1):
      • 如果相邻格子在网格范围内且未被访问过,则将其入队。
      • 更新blackCount数组,记录到达该格子时经过的最少黑色格子数量。
  3. 终止条件

    • 当到达终点(n-1, m-1)时,返回blackCount[n-1][m-1]。

实现代码

以下是这个问题的一个简单实现:

from collections import deque

def minimumBlackTiles(n, m, grid):
    # 初始化队列,visited数组和blackCount数组
    queue = deque([(0, 0, grid[0][0])])
    visited = [[False] * m for _ in range(n)]
    visited[0][0] = True
    blackCount = [[0] * m for _ in range(n)]
    blackCount[0][0] = grid[0][0]
    
    # 四个方向的移动
    directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]
    
    # BFS
    for x, y, count in queue:
        if x == n - 1 and y == m - 1:
            return count
        for dx, dy in directions:
            nx, ny = x + dx, y + dy
            if 0 <= nx < n and 0 <= ny < m and not visited[nx][ny]:
                visited[nx][ny] = True
                new_count = count + grid[nx][ny]
                blackCount[nx][ny] = min(blackCount[nx][ny], new_count)
                queue.append((nx, ny, new_count))
    return blackCount[n-1][m-1]

# 示例
n = 5
m = 5
grid = [[1, 1, 0, 0, 0],
        [0, 1, 0, 0, 1],
        [1, 0, 0, 1, 1],
        [0, 0, 1, 0, 0],
        [1, 0, 1, 1, 0]]
print(minimumBlackTiles(n, m, grid))  # 输出:2

实践感悟

通过这个问题,我深刻体会到了广度优先搜索(BFS)在解决最短路径问题中的应用。BFS可以保证我们找到的路径是最短路径,这对于最小化穿越黑色格子的问题至关重要。