青训营X豆包MarsCode 实践记录AI助力 矩形棋盘路径问题 | 豆包MarsCode AI 刷题

99 阅读4分钟

问题描述

小R正在玩一个迷宫游戏。他的起始位置位于一个n行m列的矩形棋盘的左上角 (1,1),目标是移动到棋盘的右下角 (n,m)。棋盘上的每个格子要么是道路("0"),要么是障碍("1")。小R每次只能向右或向下移动,而且必须避开障碍。请你计算小R从 (1,1) 移动到 (n,m) 的所有可能路径数,并将结果对 10^9 + 7 取模。


测试样例

样例1:

输入:n = 2, m = 3, maze = ["000", "100"] 输出:2

样例2:

输入:n = 5, m = 5, maze = ["00000", "10000", "10000", "00000", "00000"] 输出:35

样例3:

输入:n = 3, m = 3, maze = ["010", "010", "000"] 输出:1

这个问题是一个典型的 动态规划 问题,目标是计算从起点 (1,1) 到终点 (n,m) 的所有可能路径数。由于每次只能向右或向下移动,而且必须避开障碍,我们可以通过动态规划来解决。

思路分析

虽然这个题的类别是图论的知识,但是这个问题可以通过 动态规划来求解。

需要从起点 (1,1) 移动到终点 (n,m),并且每次只能向右或向下移动。为了计算所有可能的路径数,定义一个状态表示当前位置的路径数,并通过状态转移来逐步求解。

  1. 题目分析 我们需要计算从起点 (1,1) 到终点 (n,m) 的所有有效路径数。 每次只能向右或向下移动,而且要避开障碍(表示为 "1")。

    ok这就是写代码时一个要注意的点。

    目标是计算从起点到终点的所有路径数,并对结果取模 10^9 + 7。

    取模的知识还记得吧

  2. 动态规划的状态定义 状态定义: 设 dp[i][j] 表示从起点 (1,1) 到达位置 (i+1, j+1) 的路径数。

    dp[i][j] 的值是从 (i,j) 位置的前一步移动过来的路径数之和。 起始条件:起点 (1,1) 处的路径数为 1,即 dp[0][0] = 1,表示从起点到起点只有一种方式,就是不动。

    转移方程: 对于每个位置 (i,j),可以从上方 (i-1,j) 或者左方 (i,j-1) 移动过来:

    如果当前位置 (i,j) 不是障碍(即 maze[i][j] == '0'),则: dp[i][j] = dp[i-1][j] + dp[i][j-1],表示从上方或者左方两种情况的路径数相加。 如果当前位置是障碍(即 maze[i][j] == '1'),则 dp[i][j] = 0,表示该位置无法到达。

  3. 边界条件 起点:dp[0][0] = 1,即从起点出发的路径数是 1,如果起点有障碍,直接返回 0,因为无法开始。 障碍物:如果当前位置是障碍,则 dp[i][j] = 0,表示无法到达该位置。

  4. 状态转移过程 遍历棋盘的每一个位置 (i, j),并根据以下规则更新 dp[i][j]: 如果 maze[i][j] == '1',表示该位置是障碍,dp[i][j] = 0。 否则,计算路径数: 如果上方有位置(即 i > 0),则可以从上方来:dp[i][j] += dp[i-1][j]。 如果左方有位置(即 j > 0),则可以从左方来:dp[i][j] += dp[i][j-1]。 对路径数 dp[i][j] 进行取模操作,防止溢出。

  5. 最终结果 最终结果是 dp[n-1][m-1],即从 (1,1) 到 (n,m) 的路径数。返回该值并对 10^9 + 7 取模。

  6. 特例处理 起点或终点是障碍:如果起点或者终点是障碍,显然无法走到终点,直接返回 0。

  7. 时间复杂度分析 我们需要遍历棋盘的每个位置并更新 dp 数组的值。每个位置的更新是常数时间操作。 因此,时间复杂度为 O(n * m),其中 n 是行数,m 是列数。

  8. 空间复杂度分析 我们使用了一个二维数组 dp 来保存每个位置的路径数,因此空间复杂度为 O(n * m)。

好了基本的思路就是这样,接下来就是编码阶段

有没有发现动态规划的题目有很多类似的地方

image.png