【蓝桥杯】算法笔记4

1. 网格路径计数(含障碍物)

1.1. 问题描述

给定一个 m x n 的网格,其中某些格子有障碍物不能通过。机器人从左上角 (0, 0) 出发,每次只能向右或向下移动一步,问到达右下角 (m-1, n-1) 有多少条不同的路径?

输入格式

第一行:两个整数 m 和 n(1 ≤ m, n ≤ 100),表示网格的行数和列数

接下来 m 行:每行 n 个整数(0 或 1),0 表示可通过的空格子,1 表示障碍物

输出格式

一个整数,表示不同路径的数量

示例输入

3 3
0 0 0
0 1 0
0 0 0

示例输出

2

1.2. 分析

1. 理解问题:这是一个典型的动态规划问题。我们需要计算从起点到终点的所有可能路径,但要考虑障碍物的限制。

2. 确定状态:定义 dp[i][j] 表示从 (0,0) 到达 (i,j) 的路径数量。

3. 状态转移方程:对于每个格子 (i,j),

扫描二维码关注公众号,回复: 17548183 查看本文章
  • 如果它是障碍物(grid[i][j] == 1),则 dp[i][j] = 0(无法到达)

  • 否则,dp[i][j] = dp[i-1][j] + dp[i][j-1](从上边或左边来的路径之和)

4. 初始化

  • dp[0][0]:如果起点不是障碍物,则为1,否则为0

  • 第一行和第一列需要特殊处理,因为它们只能从一个方向来

5. 边界条件

  • 当 i=0 或 j=0 时,只能从左边或上边来

  • 遇到障碍物时,该点的路径数置为0

6. 计算顺序:按行或按列顺序计算,确保计算 dp[i][j] 时 dp[i-1][j] 和 dp[i][j-1] 已经计算过

7. 最终结果:dp[m-1][n-1] 即为所求

1.3. 代码

def uniquePathsWithObstacles(grid):
    m = len(grid)    # 网格的行数
    n = len(grid[0]) # 网格的列数
    
    # 创建一个 m x n 的二维数组来存储路径数
    dp = [[0] * n for _ in range(m)]
    
    # 初始化起点
    dp[0][0] = 1 if grid[0][0] == 0 else 0
    
    # 初始化第一列:只能从上边来
    for i in range(1, m):
        if grid[i][0] == 0:  # 当前格子不是障碍物
            dp[i][0] = dp[i-1][0]  # 只能从上边来
        else:
            dp[i][0] = 0  # 遇到障碍物,路径数为0
    
    # 初始化第一行:只能从左边来
    for j in range(1, n):
        if grid[0][j] == 0:  # 当前格子不是障碍物
            dp[0][j] = dp[0][j-1]  # 只能从左边来
        else:
            dp[0][j] = 0  # 遇到障碍物,路径数为0
    
    # 填充剩余网格
    for i in range(1, m):
        for j in range(1, n):
            if grid[i][j] == 1:  # 如果是障碍物
                dp[i][j] = 0
            else:
                # 路径数 = 从上边来的路径数 + 从左边来的路径数
                dp[i][j] = dp[i-1][j] + dp[i][j-1]
    
    return dp[m-1][n-1]

# 读取输入
m, n = map(int, input().split())
grid = []
for _ in range(m):
    row = list(map(int, input().split()))
    grid.append(row)

# 计算并输出结果
print(uniquePathsWithObstacles(grid))

时间复杂度:O(m×n),需要遍历整个网格一次。

空间复杂度:O(m×n),用于存储 dp 数组。可以优化到 O(n) 或 O(m) 使用滚动数组。

对于示例输入:

3 3
0 0 0
0 1 0
0 0 0

dp 数组的填充过程:

  1. 初始化 dp[0][0] = 1

  2. 第一列:dp[1][0] = 1, dp[2][0] = 1

  3. 第一行:dp[0][1] = 1, dp[0][2] = 1

  4. dp[1][1] = 0(因为 grid[1][1] 是障碍物)

  5. dp[1][2] = dp[0][2] + dp[1][1] = 1 + 0 = 1

  6. dp[2][1] = dp[1][1] + dp[2][0] = 0 + 1 = 1

  7. dp[2][2] = dp[1][2] + dp[2][1] = 1 + 1 = 2

    <