📌  相关文章
📜  从矩阵的左上角到右下角的最小成本(1)

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

从矩阵的左上角到右下角的最小成本

在计算机科学中,从矩阵的左上角到右下角的最小成本,是一种经典的算法问题,通常用于矩阵路径搜索和优化问题。

问题描述

给定一个m x n的矩阵,矩阵中的每个元素都代表通过该位置的成本。从矩阵的左上角开始,只能向右或向下移动。到达矩阵的右下角的最小成本是多少?

例如,给定以下3 x 3的矩阵

[
    [1, 3, 1],
    [1, 5, 1],
    [4, 2, 1]
]

从左上角到右下角的最小成本为7(1+3+1+1+1)。

解决方案
暴力枚举

最朴素的解决方案是暴力枚举,即枚举所有从左上角到右下角的路径。由于每个位置只能向右或向下移动,因此总路径数是 C(m+n,m) 。对于每条路径,都需要计算它的成本。由此可得,暴力枚举的时间复杂度为 O(C(m+n,m) * mn) ,显然在实际应用中不可行。

动态规划

动态规划(Dynamic Programming,简称 DP)是一种高效的算法思想,可用于解决大部分优化问题,包括从矩阵的左上角到右下角的最小成本问题。

该问题可以用动态规划的思想描述为,先定义一个状态转移方程 dp[i][j] ,表示从矩阵的左上角到达 (i,j) 位置的最小成本。由此可得状态转移方程:

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

其中, cost[i][j] 是矩阵 (i,j) 位置的成本, dp[0][0] 为矩阵左上角的成本。

根据状态转移方程,可用递推的方式求得矩阵右下角的最小成本。代码如下:

def minCost(cost: List[List[int]]) -> int:
    m, n = len(cost), len(cost[0])
    dp = [[0] * n for _ in range(m)]
    dp[0][0] = cost[0][0]

    # 初始化第一列和第一行
    for i in range(1, m):
        dp[i][0] = dp[i-1][0] + cost[i][0]
    for j in range(1, n):
        dp[0][j] = dp[0][j-1] + cost[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]) + cost[i][j]

    return dp[m-1][n-1]

该算法的时间复杂度为 O(mn) ,空间复杂度为 O(mn) 。由此可见,动态规划是一种高效的解决方法。

总结

从矩阵的左上角到右下角的最小成本问题是一种经典的算法问题,常用于矩阵路径搜索和优化问题。暴力枚举虽然简单易懂,但时间复杂度太高。动态规划思想可以大幅度提高计算效率,是解决该问题的主流方法。