📜  矩阵中从入口到出口的路径和最大路径总和

📅  最后修改于: 2021-04-26 17:51:43             🧑  作者: Mango

给定一个迷宫,它是一个N * N格grid [] [] 。迷宫的每一个细胞包含任一数字1,23,其中移动定义为:

  • 如果grid [i] [j] = 1,则唯一有效的移动是grid [i] [j + 1]
  • 如果grid [i] [j] = 2,则唯一有效的移动是grid [i + 1] [j]
  • 如果grid [i] [j] = 3,则有效移动是grid [i] [j + 1]grid [i +1] [j]

现在,任务是查找从grid [0] [0]grid [N – 1] [N – 1]的所有路径的计数,以及所有路径中的最大可能和,即当所有值都已访问时单元格加到总和中。

例子:

方法:可以使用动态编程解决此问题。
要计算路径数,请创建一个dp [] []数组,其中dp [i] [j]将存储从grid [i] [j]grid [N – 1] [N – 1]的路径数,并递归关系将是

  1. 如果grid [i] [j] = 1,则dp [i] [j] = dp [i] [j + 1]。
  2. 如果grid [i] [j] = 2,则dp [i] [j] = dp [i + 1] [j]。
  3. 如果grid [i] [j] = 1,则dp [i] [j] = dp [i] [j + 1] + dp [i +1] [j]。

并且终止条件将是当源和目标相同时,即dp [N – 1] [N – 1] = 1

现在,要找到最大求和路径,可以创建另一个dp [] []数组,其中dp [i] [j]将存储从grid [i] [j]grid [N – 1]的路径的最大和。 [N – 1] ,则递归关系为

  1. 如果grid [i] [j] = 1,则dp [i] [j] = grid [i] [j] + dp [i] [j +1]。
  2. 如果grid [i] [j] = 2,则dp [i] [j] = grid [i] [j] + dp [i + 1] [j]。
  3. 如果grid [i] [j] = 1,则dp [i] [j] = grid [i] [j] + max(dp [i] [j + 1] + dp [i +1] [j])。

并且终止条件将再次是当源和目标相同时,即dp [N – 1] [N – 1] = grid [N – 1] [N – 1]

C++
// C++ implementation of the approach
#include
#define COL 5
#define ROW 5
using namespace std;
  
// Recursive function to return the total
// paths from grid[i][j] to grid[n - 1][n - 1]
int totalPaths(int i, int j, int n, 
                int grid[][COL], int dp[][COL])
{
  
    // Out of bounds
    if (i < 0 || j < 0 || i >= n || j >= n)
        return 0;
  
    // If the current state hasn't been solved before
    if (dp[i][j] == -1) 
    {
  
        // Only valid move is right
        if (grid[i][j] == 1)
            dp[i][j] = totalPaths(i, j + 1, n, grid, dp);
  
        // Only valid move is down
        else if (grid[i][j] == 2)
            dp[i][j] = totalPaths(i + 1, j, n, grid, dp);
  
        // Right and down, both are valid moves
        else
            dp[i][j] = totalPaths(i, j + 1, n, grid, dp)
                    + totalPaths(i + 1, j, n, grid, dp);
    }
    return dp[i][j];
}
  
  
// Recursive function to return the maximum
// sum along the path from grid[i][j] to grid[n - 1][n - 1]
int maxSumPath(int i, int j, int n, 
                int grid[ROW][COL], int dp[ROW][COL])
{
  
    // Out of bounds
    if (i < 0 || j < 0 || i >= n || j >= n)
        return 0;
  
    // If the current state hasn't been solved before
    if (dp[i][j] == -1)
    {
  
        // Only valid move is right
        if (grid[i][j] == 1)
            dp[i][j] = grid[i][j] + maxSumPath(i, 
                                    j + 1, n, grid, dp);
  
        // Only valid move is down
        else if (grid[i][j] == 2)
            dp[i][j] = grid[i][j] + maxSumPath(i + 1,
                                    j, n, grid, dp);
  
        // Right and down, both are valid moves
        else
            dp[i][j] = grid[i][j]
                    + max(maxSumPath(i, j + 1, n, grid, dp),
                        maxSumPath(i + 1, j, n, grid, dp));
    }
    return dp[i][j];
}
  
// Driver code
int main()
{
    int grid[ROW][COL] = { { 1, 1, 3, 2, 1 },
                           { 3, 2, 2, 1, 2 },
                           { 1, 3, 3, 1, 3 },
                           { 1, 2, 3, 1, 2 },
                           { 1, 1, 1, 3, 1 } };
    int n = ROW;
  
    // Fill the dp[][] array with -1
    int dp[ROW][COL];
      
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < n; j++)
        dp[i][j] = -1;
    }
  
    // When source and destination are same
    // then there is only 1 path
    dp[n - 1][n - 1] = 1;
  
    // Print the count of paths from
    // grid[0][0] to grid[n - 1][n - 1]
    cout<<"Total paths: "
        << totalPaths(0, 0, n, grid, dp) << endl;
  
    // Fill the dp[][] array again with -1
    //for (int i = 0; i < n; i++)
    // Arrays.fill(dp[i], -1);
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < n; j++)
        dp[i][j] = -1;
    }
  
    // When source and destination are same
    // then the sum is grid[n - 1][n - 1]
    dp[n - 1][n - 1] = grid[n - 1][n - 1];
  
    // Print the maximum sum among all the paths
    // from grid[0][0] to grid[n - 1][n - 1]
    cout<< "Maximum sum: "
        << maxSumPath(0, 0, n, grid, dp)<


Java
// Java implementation of the approach
import java.util.Arrays;
  
class GFG {
  
    // Recursive function to return the total
    // paths from grid[i][j] to grid[n - 1][n - 1]
    static int totalPaths(int i, int j, int n, int grid[][], int dp[][])
    {
  
        // Out of bounds
        if (i < 0 || j < 0 || i >= n || j >= n)
            return 0;
  
        // If the current state hasn't been solved before
        if (dp[i][j] == -1) {
  
            // Only valid move is right
            if (grid[i][j] == 1)
                dp[i][j] = totalPaths(i, j + 1, n, grid, dp);
  
            // Only valid move is down
            else if (grid[i][j] == 2)
                dp[i][j] = totalPaths(i + 1, j, n, grid, dp);
  
            // Right and down, both are valid moves
            else
                dp[i][j] = totalPaths(i, j + 1, n, grid, dp)
                           + totalPaths(i + 1, j, n, grid, dp);
        }
        return dp[i][j];
    }
  
    // Recursive function to return the maximum
    // sum along the path from grid[i][j] to grid[n - 1][n - 1]
    static int maxSumPath(int i, int j, int n, int grid[][], int dp[][])
    {
  
        // Out of bounds
        if (i < 0 || j < 0 || i >= n || j >= n)
            return 0;
  
        // If the current state hasn't been solved before
        if (dp[i][j] == -1) {
  
            // Only valid move is right
            if (grid[i][j] == 1)
                dp[i][j] = grid[i][j] + maxSumPath(i, j + 1, n, grid, dp);
  
            // Only valid move is down
            else if (grid[i][j] == 2)
                dp[i][j] = grid[i][j] + maxSumPath(i + 1, j, n, grid, dp);
  
            // Right and down, both are valid moves
            else
                dp[i][j] = grid[i][j]
                           + Math.max(maxSumPath(i, j + 1, n, grid, dp),
                                      maxSumPath(i + 1, j, n, grid, dp));
        }
        return dp[i][j];
    }
  
    // Driver code
    public static void main(String[] args)
    {
        int grid[][] = { { 1, 1, 3, 2, 1 },
                         { 3, 2, 2, 1, 2 },
                         { 1, 3, 3, 1, 3 },
                         { 1, 2, 3, 1, 2 },
                         { 1, 1, 1, 3, 1 } };
        int n = grid.length;
  
        // Fill the dp[][] array with -1
        int dp[][] = new int[n][n];
        for (int i = 0; i < n; i++)
            Arrays.fill(dp[i], -1);
  
        // When source and destination are same
        // then there is only 1 path
        dp[n - 1][n - 1] = 1;
  
        // Print the count of paths from
        // grid[0][0] to grid[n - 1][n - 1]
        System.out.println("Total paths: "
                           + totalPaths(0, 0, n, grid, dp));
  
        // Fill the dp[][] array again with -1
        for (int i = 0; i < n; i++)
            Arrays.fill(dp[i], -1);
  
        // When source and destination are same
        // then the sum is grid[n - 1][n - 1]
        dp[n - 1][n - 1] = grid[n - 1][n - 1];
  
        // Print the maximum sum among all the paths
        // from grid[0][0] to grid[n - 1][n - 1]
        System.out.println("Maximum sum: "
                           + maxSumPath(0, 0, n, grid, dp));
    }
}


Python3
# Python3 implementation of the approach 
  
# Recursive function to return the total 
# paths from grid[i][j] to grid[n - 1][n - 1] 
def totalPaths(i, j, n, grid, dp): 
  
    # Out of bounds 
    if (i < 0 or j < 0 or i >= n or j >= n): 
        return 0
  
    # If the current state 
    # hasn't been solved before 
    if (dp[i][j] == -1): 
      
        # Only valid move is right 
        if (grid[i][j] == 1): 
            dp[i][j] = totalPaths(i, j + 1, n, grid, dp) 
  
        # Only valid move is down 
        elif (grid[i][j] == 2): 
            dp[i][j] = totalPaths(i + 1, j, n, grid, dp) 
  
        # Right and down, both are valid moves 
        else:
            dp[i][j] = totalPaths(i, j + 1, n, grid, dp) +\
                       totalPaths(i + 1, j, n, grid, dp) 
      
    return dp[i][j] 
  
# Recursive function to return the maximum 
# sum along the path from grid[i,j] to grid[n - 1,n - 1] 
def maxSumPath(i, j, n, grid, dp): 
  
    # Out of bounds 
    if (i < 0 or j < 0 or i >= n or j >= n): 
        return 0
  
    # If the current state 
    # hasn't been solved before 
    if (dp[i][j] == -1): 
      
        # Only valid move is right 
        if (grid[i][j] == 1): 
            dp[i][j] = grid[i][j] + \
                       maxSumPath(i, j + 1, n, grid, dp) 
  
        # Only valid move is down 
        elif (grid[i][j] == 2): 
            dp[i][j] = grid[i][j] + \
                       maxSumPath(i + 1, j, n, grid, dp) 
  
        # Right and down, both are valid moves 
        else:
            dp[i][j] = grid[i][j] + \
                       max(maxSumPath(i, j + 1, n, grid, dp), 
                           maxSumPath(i + 1, j, n, grid, dp)) 
      
    return dp[i][j] 
  
# Driver code 
if __name__ == '__main__':
      
    grid = [[ 1, 1, 3, 2, 1 ], 
            [ 3, 2, 2, 1, 2 ], 
            [ 1, 3, 3, 1, 3 ], 
            [ 1, 2, 3, 1, 2 ], 
            [ 1, 1, 1, 3, 1 ]]
  
    n = len(grid[0])
  
    # Fill the dp[n][n] array with -1
    dp= [[-1] * n] * n 
  
    # When source and destination are same 
    # then there is only 1 path 
    dp[n - 1][n - 1] = 1
  
    # Print the count of paths from 
    # grid[0,0] to grid[n - 1][n - 1] 
    print("Total paths:", 
           totalPaths(0, 0, n, grid, dp)) 
  
    # Fill the dp[n][n] array again with -1 
    dp= [[-1] * n] * n 
  
    # When source and destination are same 
    # then the sum is grid[n - 1][n - 1] 
    dp[n - 1][n - 1] = grid[n - 1][n - 1] 
  
    # Print the maximum sum among all the paths 
    # from grid[0,0] to grid[n - 1][n - 1] 
    print("Maximum sum:", 
           maxSumPath(0, 0, n, grid, dp)) 
  
# This code is contributed by ashutosh450


C#
// C# implementation of the approach
using System;
  
class GFG 
{
  
// Recursive function to return the total
// paths from grid[i][j] to grid[n - 1][n - 1]
static int totalPaths(int i, int j, int n, 
                      int [,]grid, int [,]dp)
{
  
    // Out of bounds
    if (i < 0 || j < 0 || i >= n || j >= n)
        return 0;
  
    // If the current state
    // hasn't been solved before
    if (dp[i, j] == -1)
    {
  
        // Only valid move is right
        if (grid[i, j] == 1)
            dp[i, j] = totalPaths(i, j + 1, n, grid, dp);
  
        // Only valid move is down
        else if (grid[i, j] == 2)
            dp[i, j] = totalPaths(i + 1, j, n, grid, dp);
  
        // Right and down, both are valid moves
        else
            dp[i, j] = totalPaths(i, j + 1, n, grid, dp) + 
                      totalPaths(i + 1, j, n, grid, dp);
    }
    return dp[i, j];
}
  
// Recursive function to return the maximum
// sum along the path from grid[i,j] to grid[n - 1,n - 1]
static int maxSumPath(int i, int j, int n,
                      int [,]grid, int [,]dp)
{
  
    // Out of bounds
    if (i < 0 || j < 0 || i >= n || j >= n)
        return 0;
  
    // If the current state 
    // hasn't been solved before
    if (dp[i, j] == -1) 
    {
  
        // Only valid move is right
        if (grid[i, j] == 1)
            dp[i, j] = grid[i, j] + maxSumPath(i, j + 1, 
                                               n, grid, dp);
  
        // Only valid move is down
        else if (grid[i,j] == 2)
            dp[i, j] = grid[i, j] + maxSumPath(i + 1, j,
                                               n, grid, dp);
  
        // Right and down, both are valid moves
        else
            dp[i, j] = grid[i, j] + 
                       Math.Max(maxSumPath(i, j + 1, n, grid, dp), 
                                maxSumPath(i + 1, j, n, grid, dp));
    }
    return dp[i, j];
}
  
// Driver code
public static void Main(String[] args)
{
    int [,]grid = { { 1, 1, 3, 2, 1 },
                    { 3, 2, 2, 1, 2 },
                    { 1, 3, 3, 1, 3 },
                    { 1, 2, 3, 1, 2 },
                    { 1, 1, 1, 3, 1 } };
    int n = grid.GetLength(0);
  
    // Fill the dp[,] array with -1
    int [,]dp = new int[n, n];
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            dp[i, j] = -1;
  
    // When source and destination are same
    // then there is only 1 path
    dp[n - 1, n - 1] = 1;
  
    // Print the count of paths from
    // grid[0,0] to grid[n - 1,n - 1]
    Console.WriteLine("Total paths: " + 
                       totalPaths(0, 0, n, grid, dp));
  
    // Fill the dp[,] array again with -1
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            dp[i, j] = -1;
  
    // When source and destination are same
    // then the sum is grid[n - 1,n - 1]
    dp[n - 1, n - 1] = grid[n - 1, n - 1];
  
    // Print the maximum sum among all the paths
    // from grid[0,0] to grid[n - 1,n - 1]
    Console.WriteLine("Maximum sum: " + 
                       maxSumPath(0, 0, n, grid, dp));
}
}
  
// This code is contributed by Princi Singh


输出:
Total paths: 4
Maximum sum: 18

时间复杂度: O(n 2 )
空间复杂度: O(n 2 )