📌  相关文章
📜  查找达到矩阵末尾所需的最低限度的步骤|套装2(1)

📅  最后修改于: 2023-12-03 15:10:47.102000             🧑  作者: Mango

查找达到矩阵末尾所需的最低限度的步骤|套装2

在矩阵操作中,经常需要查找从矩阵起点到达末尾的最低步数,本套装提供多种算法解决该问题。

算法1:动态规划

使用动态规划,设$dp[i][j]$表示从起点矩阵[0][0]到达当前位置[i][j]所需的步数。则状态转移方程为:

$$dp[i][j]=min(dp[i-1][j],dp[i][j-1])+grid[i][j]$$

其中$grid[i][j]$表示矩阵当前位置的值。

算法1代码:

def minPathSum(grid):
    m,n = len(grid),len(grid[0])
    dp = [[0] * n for _ in range(m)]
    dp[0][0] = grid[0][0]
    for i in range(1,m):
        dp[i][0] = dp[i-1][0] + grid[i][0]
    for j in range(1,n):
        dp[0][j] = dp[0][j-1] + grid[0][j]
    for i in range(1,m):
        for j in range(1,n):
            dp[i][j] = min(dp[i-1][j],dp[i][j-1]) + grid[i][j]
    return dp[-1][-1]

时间复杂度:$O(mn)$

算法2:深度优先搜索

使用深度优先搜索,逐步遍历矩阵,记录当前步数。若当前步数+到终点的距离大于已知最小步数,则停止搜索。若能到达终点,则更新最小步数。

算法2代码:

def minPathSum(grid):
    m,n = len(grid),len(grid[0])
    res = float('inf')
    def dfs(i,j,step):
        nonlocal res
        if step+grid[i][j]>res:  # 剪枝
            return
        if i == m-1 and j == n-1:
            res = min(res,step+grid[i][j])
            return
        if i<m-1:
            dfs(i+1,j,step+grid[i][j])
        if j<n-1:
            dfs(i,j+1,step+grid[i][j])
    dfs(0,0,0)
    return res

时间复杂度:$O(2^{m+n})$

算法3:广度优先搜索

使用广度优先搜索,逐步遍历矩阵每一格,拓展下一步的可达位置,记录当前步数。若到达终点,则更新最小步数。

算法3代码:

import queue
def minPathSum(grid):
    m,n = len(grid),len(grid[0])
    q = queue.Queue()
    q.put((0,0,0))
    while not q.empty():
        i,j,step = q.get()
        if i == m-1 and j == n-1:
            return step+grid[i][j]
        if i<m-1:
            q.put((i+1,j,step+grid[i][j]))
        if j<n-1:
            q.put((i,j+1,step+grid[i][j]))
    return -1

时间复杂度:$O(mn)$

对于本问题,使用动态规划算法1效率最高,时间复杂度为O(mn),是常规算法之中最优解。而深度优先搜索和广度优先搜索虽然时间复杂度较高,但对于一些复杂矩阵场景,搜索算法可以获得最优解。