📌  相关文章
📜  矩阵中从左上角到右下角的最大和路径

📅  最后修改于: 2021-09-17 07:36:54             🧑  作者: Mango

给定一个维度为N * M的矩阵mat[][] ,任务是找到从左上角单元格(0, 0) 到右下角单元格(N – 1, M – 1) 的路径。矩阵,使得路径中元素的总和最大。从矩阵的任何单元格 (i, j) 允许的唯一移动是(i + 1, j)(i, j + 1)

例子:

方法一(自下而上):思路是用动态规划来解决这个问题。关键观察是单元格 grid[i][j]只能从grid[i – 1][j]grid[i][j – 1]到达。因此,该问题的递推关系由以下等式给出:

  1. 初始化维度为N * M的辅助矩阵sum[][]
  2. 迭代矩阵元素并使用上述形成的递推关系更新辅助矩阵sum[][] 的每个单元格。
  3. 完成上述步骤后,将值总和[N] [M]将包含从左上角到给定矩阵的右下角的路径的最大总和可能的。打印那个总和。

下面是上述方法的实现:

C++
// C++ program for the above approach
 
#include 
using namespace std;
 
// Function to find the maximum sum
// path in the grid
int MaximumPath(vector >& grid)
{
    // Dimensions of grid[][]
    int N = grid.size();
    int M = grid[0].size();
 
    // Stores maximum sum at each cell
    // sum[i][j] from cell sum[0][0]
    vector > sum;
    sum.resize(N + 1,
               vector(M + 1));
 
    // Iterate to compute the maximum
    // sum path in the grid
    for (int i = 1; i <= N; i++) {
 
        for (int j = 1; j <= M; j++) {
 
            // Update the maximum path sum
            sum[i][j] = max(sum[i - 1][j],
                            sum[i][j - 1])
                        + grid[i - 1][j - 1];
        }
    }
 
    // Return the maximum sum
    return sum[N][M];
}
 
// Driver Code
int main()
{
    vector > grid
        = { { 1, 2 }, { 3, 5 } };
 
    cout << MaximumPath(grid);
 
    return 0;
}


Java
// Java program for
//the above approach
import java.util.*;
class GFG{
 
// Function to find the maximum sum
// path in the grid
static int MaximumPath(int [][]grid)
{
    // Dimensions of grid[][]
    int N = grid.length;
    int M = grid[0].length;
 
    // Stores maximum sum at each cell
    // sum[i][j] from cell sum[0][0]
    int [][]sum = new int[N + 1][M + 1];
 
    // Iterate to compute the maximum
    // sum path in the grid
    for (int i = 1; i <= N; i++)
    {
        for (int j = 1; j <= M; j++)
        {
            // Update the maximum path sum
            sum[i][j] = Math.max(sum[i - 1][j],
                                 sum[i][j - 1]) +
                                 grid[i - 1][j - 1];
        }
    }
 
    // Return the maximum sum
    return sum[N][M];
}
 
// Driver Code
public static void main(String[] args)
{
  int [][]grid = {{1, 2}, {3, 5}};
  System.out.print(MaximumPath(grid));
}
}
 
// This code is contributed by shikhasingrajput


Python3
# Python3 program for the above approach
 
# Function to find the maximum sum
# path in the grid
def MaximumPath(grid):
 
    # Dimensions of grid[][]
    N = len(grid)
    M = len(grid[0])
 
    # Stores maximum sum at each cell
    # sum[i][j] from cell sum[0][0]
    sum = [[0 for i in range(M + 1)]
              for i in range(N + 1)]
 
    # Iterate to compute the maximum
    # sum path in the grid
    for i in range(1, N + 1):
        for j in range(1, M + 1):
 
            # Update the maximum path sum
            sum[i][j] = (max(sum[i - 1][j],
                             sum[i][j - 1]) +
                        grid[i - 1][j - 1])
 
    # Return the maximum sum
    return sum[N][M]
 
# Driver Code
if __name__ == '__main__':
 
    grid = [ [ 1, 2 ], [ 3, 5 ] ]
 
    print(MaximumPath(grid))
 
# This code is contributed by mohit kumar 29


C#
// C# program for the above approach
using System;
 
class GFG{
 
// Function to find the maximum sum
// path in the grid
static int MaximumPath(int [,]grid)
{
     
    // Dimensions of grid[,]
    int N = grid.GetLength(0);
    int M = grid.GetLength(1);
 
    // Stores maximum sum at each cell
    // sum[i,j] from cell sum[0,0]
    int [,]sum = new int[N + 1, M + 1];
 
    // Iterate to compute the maximum
    // sum path in the grid
    for(int i = 1; i <= N; i++)
    {
        for(int j = 1; j <= M; j++)
        {
            // Update the maximum path sum
            sum[i, j] = Math.Max(sum[i - 1, j],
                                 sum[i, j - 1]) +
                                grid[i - 1, j - 1];
        }
    }
 
    // Return the maximum sum
    return sum[N, M];
}
 
// Driver Code
public static void Main(String[] args)
{
    int [,]grid = { { 1, 2 }, { 3, 5 } };
     
    Console.Write(MaximumPath(grid));
}
}
 
// This code is contributed by Amit Katiyar


Javascript


C++
#include 
using namespace std;
 
vector > dp;
 
// Function to find the maximum sum path in the grid
int MaximumPathUtil(int i, int j, vector >& grid)
{
    // Base condition
      if (i == 0 || j == 0)
        return 0;
 
      // If current subproblem is already computed,
      // we simply return its result from the dp table
      if (dp[i][j] != -1)
        return dp[i][j];
 
      // Computing the current subproblem and
      // store the result in the dp table for future use
      return dp[i][j] = max(MaximumPathUtil(i, j-1, grid), MaximumPathUtil(i - 1, j, grid)) +
                        grid[i-1][j-1];
}
 
int MaximumPath(vector >& grid)
{
    // Dimensions of grid[][]
    int n = grid.size();
    int m = grid[0].size();
 
      // dp table to memoize the subproblem results
      dp.resize(n+1, vector (m+1, -1));
 
      // dp[n][m] gives the max. path sum
      // from grid[0][0] to grid[n-1][m-1]
      return MaximumPathUtil(n, m, grid);
}
 
// Driver Code
int main()
{
    vector > grid = {{3, 7, 9, 2, 7},
                                 {9, 8, 3, 5, 5},
                                 {1, 7, 9, 8, 6},
                                 {3, 8, 6, 4, 9},
                                 {6, 3, 9, 7, 8}};
 
    cout << MaximumPath(grid);
    return 0;
}
 
// This code is contributed by tridib_samanta


输出:
9

时间复杂度: O(N * M)
辅助空间: O(N * M)

方法二(自顶向下):我们会以自顶向下的方式递归解决问题。我们根据到达单元格 grid[i][j]的两种方式制定递归如下:

  1. 如果我们从单元格 grid[i][j-1]向右移动一步,或者,
  2. 如果我们从单元格 grid[i-1][j]向下移动一步

因此,我们需要选择给我们最大值的步骤(在上述两个之间)。此外,我们需要添加存在于我们步入的单元格中的值,即grid[i][j] 。由于这个问题具有重叠子问题的性质,我们可以将子问题的结果(memoize)存储在一个二维矩阵中(我们称之为dp ),以避免重复计算相同的子问题。最初,我们将dp表中的所有单元格设置为值 -1,并且每次找到子问题的答案时,我们都会在dp表中的相应单元格中覆盖其结果。因此,在计算任何子问题之前,我们曾经检查过 – 如果该特定子问题之前已解决或未解决,如果已解决(即其对应的单元格dp矩阵不是 -1)我们简单地返回该值,否则我们解决它并将结果存储在dp表中。

下面是上述方法的实现:

C++

#include 
using namespace std;
 
vector > dp;
 
// Function to find the maximum sum path in the grid
int MaximumPathUtil(int i, int j, vector >& grid)
{
    // Base condition
      if (i == 0 || j == 0)
        return 0;
 
      // If current subproblem is already computed,
      // we simply return its result from the dp table
      if (dp[i][j] != -1)
        return dp[i][j];
 
      // Computing the current subproblem and
      // store the result in the dp table for future use
      return dp[i][j] = max(MaximumPathUtil(i, j-1, grid), MaximumPathUtil(i - 1, j, grid)) +
                        grid[i-1][j-1];
}
 
int MaximumPath(vector >& grid)
{
    // Dimensions of grid[][]
    int n = grid.size();
    int m = grid[0].size();
 
      // dp table to memoize the subproblem results
      dp.resize(n+1, vector (m+1, -1));
 
      // dp[n][m] gives the max. path sum
      // from grid[0][0] to grid[n-1][m-1]
      return MaximumPathUtil(n, m, grid);
}
 
// Driver Code
int main()
{
    vector > grid = {{3, 7, 9, 2, 7},
                                 {9, 8, 3, 5, 5},
                                 {1, 7, 9, 8, 6},
                                 {3, 8, 6, 4, 9},
                                 {6, 3, 9, 7, 8}};
 
    cout << MaximumPath(grid);
    return 0;
}
 
// This code is contributed by tridib_samanta

输出:

时间复杂度: O(n*m)
空间复杂度: O(n*m)

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程