Given a maze which is a N * N grid grid[][]. Every cell of the maze contains either the number 1, 2 or 3 which defines the moves as:
- If grid[i][j] = 1 then the only valid move is grid[i][j + 1].
- If grid[i][j] = 2 then the only valid move is grid[i + 1][j].
- If grid[i][j] = 3 then the valid moves are grid[i][j + 1] and grid[i + 1][j].
Now, the task is to find the count of all the paths from grid[0][0] to grid[N – 1][N – 1] and the maximum possible sum among all the paths i.e. when all the values at the visited cells are added to the sum.
Examples:
Input: grid[][] = {
{3, 2},
{3, 1}}
Output:
Total paths: 2
Maximum sum: 7
The two valid paths are
(0, 0) -> (0, 1) -> (1, 1) with sum as 3 + 2 + 1 = 6
and (0, 0) -> (1, 0) -> (1, 1) with sum as 3 + 3 + 1 = 7
Input: 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}}
Output:
Total paths: 4
Maximum sum: 18
Approach: This problem can be solved using dynamic programming.
To count the number of paths, create a dp[][] array where dp[i][j] will store the count of paths from grid[i][j] to grid[N – 1][N – 1] and the recurrence relation will be,
- If grid[i][j] = 1 then dp[i][j] = dp[i][j + 1].
- If grid[i][j] = 2 then dp[i][j] = dp[i + 1][j].
- If grid[i][j] = 1 then dp[i][j] = dp[i][j + 1] + dp[i + 1][j].
and the termination condition will be when source and destination are same i.e. dp[N – 1][N – 1] = 1.
Now, to find the maximum sum path, another dp[][] array can be created where dp[i][j] will store the maximum sum of the path from grid[i][j] to grid[N – 1][N – 1] and the recurrence relation will be,
- If grid[i][j] = 1 then dp[i][j] = grid[i][j] + dp[i][j + 1].
- If grid[i][j] = 2 then dp[i][j] = grid[i][j] + dp[i + 1][j].
- If grid[i][j] = 1 then dp[i][j] = grid[i][j] + max(dp[i][j + 1] + dp[i + 1][j]).
and the termination condition will again be when source and destination are same i.e. dp[N – 1][N – 1] = grid[N – 1][N – 1].
// C++ implementation of the approach #include<bits/stdc++.h> #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)<<endl;
return 0;
} // This code is contributed by Rajput-Ji |
// 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 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# 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 |
<script> // Javascript implementation of the approach
// Recursive function to return the total
// paths from grid[i][j] to grid[n - 1][n - 1]
function totalPaths(i, j, n, grid, 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]
function maxSumPath(i, j, n, grid, 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];
}
let 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 ] ];
let n = grid.length;
// Fill the dp[][] array with -1
let dp = new Array(n);
for (let i = 0; i < n; i++)
{
dp[i] = new Array(n);
for (let 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]
document.write( "Total paths: " + totalPaths(0, 0, n, grid, dp) + "</br>" );
// Fill the dp[][] array again with -1
for (let i = 0; i < n; i++)
{
for (let 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]
document.write( "Maximum sum: " + maxSumPath(0, 0, n, grid, dp));
// This code is contributed by mukesh07.
</script> |
Total paths: 4 Maximum sum: 18
Time complexity: O(n2)
Space complexity: O(n2)