📌  相关文章
📜  通过给定单元格之一的矩阵从左上角到右下角的最大路径和(1)

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

从左上角到右下角的最大路径和

简介

这个问题给定了一个矩阵,寻找从左上角到右下角的路径,使路径上所有单元格的和最大。这是一个经典的动态规划问题,有多种解法。

解法
1. 暴力枚举

最简单的方法就是暴力枚举所有可能的路径,然后找到其中和最大的一条。这种方法的时间复杂度为 $O(2^{n^2})$,因为矩阵中有 $n^2$ 个单元格,每个单元格有两种状态,所以需要枚举 $2^{n^2}$ 种可能。

2. 递归法

我们可以利用递归的思想,把问题拆成更小的子问题。具体来说,我们可以定义一个函数 $f(i,j)$,表示从 $(0,0)$ 到 $(i,j)$ 的路径上的最大和。则有如下递归式:

$ f(i,j) = \begin{cases} m_{i,j} & (i=0, j=0) \ f(i-1, j) + m_{i,j} & (i>0, j=0) \ f(i, j-1) + m_{i,j} & (i=0, j>0) \ \max(f(i-1, j),f(i, j-1)) + m_{i,j} & (i>0, j>0) \end{cases} $

可以看到,$f(i,j)$ 的值只和 $f(i-1, j)$,$f(i, j-1)$ 和 $m_{i,j}$ 有关,所以我们可以使用记忆化搜索(即动态规划)来优化计算。

3. 动态规划法

可以使用一个二维数组 $dp$ 来保存每个单元格的最大路径和。具体来说,$dp[i][j]$ 表示从 $(0,0)$ 到 $(i,j)$ 的路径上的最大和,则有如下状态转移方程:

$ dp[i][j] = \begin{cases} m_{i,j} & (i=0, j=0) \ dp[i-1][j] + m_{i,j} & (i>0, j=0) \ dp[i][j-1] + m_{i,j} & (i=0, j>0) \ \max(dp[i-1][j],dp[i][j-1]) + m_{i,j} & (i>0, j>0) \end{cases} $

最终,$dp[n-1][n-1]$ 就是从左上角到右下角的最大路径和。

下面是 Python 代码示例:

def max_path_sum(matrix):
    n = len(matrix)
    dp = [[0] * n for _ in range(n)]
    dp[0][0] = matrix[0][0]
    for i in range(1, n):
        dp[i][0] = dp[i-1][0] + matrix[i][0]
        dp[0][i] = dp[0][i-1] + matrix[0][i]
    for i in range(1, n):
        for j in range(1, n):
            dp[i][j] = max(dp[i-1][j], dp[i][j-1]) + matrix[i][j]
    return dp[n-1][n-1]