Given a “m x n” matrix, count number of paths to reach bottom right from top left with maximum k turns allowed. What is a turn? A movement is considered turn, if we were moving along row and now move along column. OR we were moving along column and now move along row.
There are two possible scenarios when a turn can occur
at point (i, j):
Turns Right: (i-1, j) -> (i, j) -> (i, j+1)
Down Right
Turns Down: (i, j-1) -> (i, j) -> (i+1, j)
Right Down
Examples:
Input: m = 3, n = 3, k = 2
Output: 4

Example: For m = 3, n = 3, k = 2
See below diagram for four paths with
maximum 2 turns.
Input: m = 3, n = 3, k = 1
Output: 2
This problem can be recursively computed using below recursive formula.
countPaths(i, j, k): Count of paths to reach (i,j) from (0, 0)
countPathsDir(i, j, k, 0): Count of paths if we reach (i, j)
along row.
countPathsDir(i, j, k, 1): Count of paths if we reach (i, j)
along column.
The fourth parameter in countPathsDir() indicates direction.
Value of countPaths() can be written as:
countPaths(i, j, k) = countPathsDir(i, j, k, 0) +
countPathsDir(i, j, k, 1)
And value of countPathsDir() can be recursively defined as:
// Base cases
// If current direction is along row
If (d == 0)
// Count paths for two cases
// 1) We reach here through previous row.
// 2) We reach here through previous column, so number of
// turns k reduce by 1.
countPathsDir(i, j, k, d) = countPathsUtil(i, j-1, k, d) +
countPathsUtil(i-1, j, k-1, !d);
// If current direction is along column
Else
// Similar to above
countPathsDir(i, j, k, d) = countPathsUtil(i-1, j, k, d) +
countPathsUtil(i, j-1, k-1, !d);
We can solve this problem in Polynomial Time using Dynamic Programming. The idea is to use a 4-dimensional table dp[m][n][k][d] where m is number of rows, n is number of columns, k is number of allowed turns and d is the direction.
Below is the Dynamic Programming-based implementation.
C++14
#include<bits/stdc++.h>
using namespace std;
#define MAX 100
int dp[MAX][MAX][MAX][2];
int countPathsUtil( int i, int j, int k, int d)
{
if (i < 0 || j < 0)
return 0;
if (i == 0 && j == 0)
return 1;
if (k == 0)
{
if (d == 0 && i == 0) return 1;
if (d == 1 && j == 0) return 1;
return 0;
}
if (dp[i][j][k][d] != -1)
return dp[i][j][k][d];
if (d == 0)
return dp[i][j][k][d] = countPathsUtil(i, j-1, k, d) +
countPathsUtil(i-1, j, k-1, !d);
return dp[i][j][k][d] = countPathsUtil(i-1, j, k, d) +
countPathsUtil(i, j-1, k-1, !d);
}
int countPaths( int i, int j, int k)
{
if (i == 0 && j == 0)
return 1;
memset (dp, -1, sizeof dp);
return countPathsUtil(i-1, j, k, 1) +
countPathsUtil(i, j-1, k, 0);
}
int main()
{
int m = 3, n = 3, k = 2;
cout << "Number of paths is "
<< countPaths(m-1, n-1, k) << endl;
return 0;
}
|
Java
import java.util.*;
class GFG
{
static int MAX = 100 ;
static int [][][][]dp = new int [MAX][MAX][MAX][ 2 ];
static int countPathsUtil( int i, int j, int k, int d)
{
if (i < 0 || j < 0 )
return 0 ;
if (i == 0 && j == 0 )
return 1 ;
if (k == 0 )
{
if (d == 0 && i == 0 ) return 1 ;
if (d == 1 && j == 0 ) return 1 ;
return 0 ;
}
if (dp[i][j][k][d] != - 1 )
return dp[i][j][k][d];
if (d == 0 )
return dp[i][j][k][d] = countPathsUtil(i, j - 1 , k, d) +
countPathsUtil(i - 1 , j, k - 1 , d == 1 ? 0 : 1 );
return dp[i][j][k][d] = countPathsUtil(i - 1 , j, k, d) +
countPathsUtil(i, j - 1 , k - 1 , d == 1 ? 0 : 1 );
}
static int countPaths( int i, int j, int k)
{
if (i == 0 && j == 0 )
return 1 ;
for ( int p = 0 ; p < MAX; p++)
{
for ( int q = 0 ; q < MAX; q++)
{
for ( int r = 0 ; r < MAX; r++)
for ( int s = 0 ; s < 2 ; s++)
dp[p][q][r][s] = - 1 ;
}
}
return countPathsUtil(i - 1 , j, k, 1 ) +
countPathsUtil(i, j - 1 , k, 0 );
}
public static void main(String[] args)
{
int m = 3 , n = 3 , k = 2 ;
System.out.println( "Number of paths is " +
countPaths(m - 1 , n - 1 , k));
}
}
|
Python3
MAX = 100
dp = [[[[ - 1 for col in range ( 2 )]
for col in range ( MAX )]
for row in range ( MAX )]
for row in range ( MAX )]
def countPathsUtil(i, j, k, d):
if (i < 0 or j < 0 ):
return 0
if (i = = 0 and j = = 0 ):
return 1
if (k = = 0 ):
if (d = = 0 and i = = 0 ):
return 1
if (d = = 1 and j = = 0 ):
return 1
return 0
if (dp[i][j][k][d] ! = - 1 ):
return dp[i][j][k][d]
if (d = = 0 ):
dp[i][j][k][d] = countPathsUtil(i, j - 1 , k, d) + \
countPathsUtil(i - 1 , j, k - 1 , not d)
return dp[i][j][k][d]
dp[i][j][k][d] = countPathsUtil(i - 1 , j, k, d) + \
countPathsUtil(i, j - 1 , k - 1 , not d)
return dp[i][j][k][d]
def countPaths(i, j, k):
if (i = = 0 and j = = 0 ):
return 1
return countPathsUtil(i - 1 , j, k, 1 ) + \
countPathsUtil(i, j - 1 , k, 0 )
if __name__ = = '__main__' :
m = 3
n = 3
k = 2
print ( "Number of paths is" ,
countPaths(m - 1 , n - 1 , k))
|
C#
using System;
class GFG
{
static int MAX = 100;
static int [,,,]dp = new int [MAX, MAX, MAX, 2];
static int countPathsUtil( int i, int j, int k, int d)
{
if (i < 0 || j < 0)
return 0;
if (i == 0 && j == 0)
return 1;
if (k == 0)
{
if (d == 0 && i == 0) return 1;
if (d == 1 && j == 0) return 1;
return 0;
}
if (dp[i, j, k, d] != -1)
return dp[i, j, k, d];
if (d == 0)
return dp[i, j, k, d] = countPathsUtil(i, j - 1, k, d) +
countPathsUtil(i - 1, j, k - 1,
d == 1 ? 0 : 1);
return dp[i, j, k, d] = countPathsUtil(i - 1, j, k, d) +
countPathsUtil(i, j - 1, k - 1,
d == 1 ? 0 : 1);
}
static int countPaths( int i, int j, int k)
{
if (i == 0 && j == 0)
return 1;
for ( int p = 0; p < MAX; p++)
{
for ( int q = 0; q < MAX; q++)
{
for ( int r = 0; r < MAX; r++)
for ( int s = 0; s < 2; s++)
dp[p, q, r, s] = -1;
}
}
return countPathsUtil(i - 1, j, k, 1) +
countPathsUtil(i, j - 1, k, 0);
}
public static void Main(String[] args)
{
int m = 3, n = 3, k = 2;
Console.WriteLine( "Number of paths is " +
countPaths(m - 1, n - 1, k));
}
}
|
Javascript
<script>
const MAX = 100
let dp = new Array(MAX)
for (let i = 0; i < MAX; i++){
dp[i] = new Array(MAX)
for (let j = 0; j < MAX; j++){
dp[i][j] = new Array(MAX)
for (let k = 0; k < MAX; k++){
dp[i][j][k] = new Array(2).fill(-1)
}
}
}
function countPathsUtil(i, j, k, d){
if (i < 0 || j < 0)
return 0
if (i == 0 && j == 0)
return 1
if (k == 0){
if (d == 0 && i == 0)
return 1
if (d == 1 && j == 0)
return 1
return 0
}
if (dp[i][j][k][d] != -1)
return dp[i][j][k][d]
if (d == 0){
dp[i][j][k][d] = countPathsUtil(i, j - 1, k, d) +
countPathsUtil(i - 1, j, k - 1, d^1)
return dp[i][j][k][d]
}
dp[i][j][k][d] = countPathsUtil(i - 1, j, k, d) +
countPathsUtil(i, j - 1, k - 1, d^1)
return dp[i][j][k][d]
}
function countPaths(i, j, k){
if (i == 0 && j == 0)
return 1
return countPathsUtil(i - 1, j, k, 1) +
countPathsUtil(i, j - 1, k, 0)
}
let m = 3
let n = 3
let k = 2
document.write( "Number of paths is" ,
countPaths(m - 1, n - 1, k))
</script>
|
OutputNumber of paths is 4
Time Complexity: O(m*n*k)
Auxiliary Space: O(MAX3)
Thanks to Gaurav Ahirwar for suggesting this solution. Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.