0576. 出界的路径数
大约 4 分钟
0576. 出界的路径数
- 标签:动态规划
- 难度:中等
题目链接
题目大意
描述:有一个大小为 的网络和一个球。球的起始位置为 。你可以将球移到在四个方向上相邻的单元格内(可以穿过网格边界到达网格之外)。最多可以移动 次球。
现在给定五个整数 、、、 以及 。
要求:找出并返回可以将球移出边界的路径数量。因为答案可能非常大,返回对 取余后的结果。
说明:
- 。
- 。
- 。
- 。
示例:
- 示例 1:
输入:m = 2, n = 2, maxMove = 2, startRow = 0, startColumn = 0
输出:6
解题思路
思路 1:记忆化搜索
- 问题的状态定义为:从位置 出发,最多使用 步,可以将球移出边界的路径数量。
- 定义一个 的三维数组 用于记录已经计算过的路径数量。
- 定义递归函数 用于计算路径数量。
- 如果 已经出界,则说明找到了一条路径,返回方案数为 。
- 如果没有移动次数了,则返回方案数为 。
- 定义方案数 ,遍历四个方向,递归计算四个方向的方案数,累积到 中,并进行取余。
- 返回方案数 。
- 调用递归函数 ,并将其返回值作为答案进行返回。
思路 1:代码
class Solution:
def findPaths(self, m: int, n: int, maxMove: int, startRow: int, startColumn: int) -> int:
directions = {(1, 0), (-1, 0), (0, 1), (0, -1)}
mod = 10 ** 9 + 7
memo = [[[-1 for _ in range(maxMove + 1)] for _ in range(n)] for _ in range(m)]
def dfs(i, j, moveCount):
if i < 0 or i >= m or j < 0 or j >= n:
return 1
if moveCount == 0:
return 0
if memo[i][j][moveCount] != -1:
return memo[i][j][moveCount]
ans = 0
for direction in directions:
new_i = i + direction[0]
new_j = j + direction[1]
ans += dfs(new_i, new_j, moveCount - 1)
ans %= mod
memo[i][j][moveCount] = ans
return ans
return dfs(startRow, startColumn, maxMove)
思路 1:复杂度分析
- 时间复杂度:。
- 空间复杂度:。
思路 2:动态规划
我们需要统计从 位置出发,最多移动 次能够穿过边界的所有路径数量。则我们可以根据位置和移动步数来划分阶段和定义状态。
1. 划分阶段
按照位置进行阶段划分。
2. 定义状态
定义状态 表示为:从位置 最多移动 次最终穿过边界的所有路径数量。
3. 状态转移方程
因为球可以在上下左右四个方向上进行移动,所以对于位置 ,最多移动 次最终穿过边界的所有路径数量取决于周围四个方向上最多经过 次穿过对应位置上的所有路径数量和。
即:。
4. 初始条件
如果位置 已经处于边缘,只差一步就穿过边界。则此时位置 最多移动 次最终穿过边界的所有路径数量取决于有相邻多少个方向是边界。也可以通过对上面 、、、 是否已经穿过边界进行判断(每一个方向穿过一次,就累积一次),来计算路径数目。然后将其作为初始条件。
5. 最终结果
根据我们之前定义的状态, 表示为:从位置 最多移动 次最终穿过边界的所有路径数量。则最终答案为 。
思路 2:动态规划代码
class Solution:
def findPaths(self, m: int, n: int, maxMove: int, startRow: int, startColumn: int) -> int:
directions = {(1, 0), (-1, 0), (0, 1), (0, -1)}
mod = 10 ** 9 + 7
dp = [[[0 for _ in range(maxMove + 1)] for _ in range(n)] for _ in range(m)]
for i in r
for k in range(1, maxMove + 1):
for i in range(m):
for j in range(n):
for direction in directions:
new_i = i + direction[0]
new_j = j + direction[1]
if 0 <= new_i < m and 0 <= new_j < n:
dp[i][j][k] = (dp[i][j][k] + dp[new_i][new_j][k - 1]) % mod
else:
dp[i][j][k] = (dp[i][j][k] + 1) % mod
return dp[startRow][startColumn][maxMove]
思路 2:复杂度分析
- 时间复杂度:。三重循环遍历的时间复杂度为 。
- 空间复杂度:。使用了三维数组保存状态,所以总体空间复杂度为 。