Given three integers M, N and K, the task is to count all the possible paths from the cell (0, 0, 0) to cell (M-1, N-1, K-1) in a matrix of size (M, N, K). Movement is allowed only in three directions, which are along the positive direction of the three axes i.e. from any cell (i, j, k) movement is allowed to cells (i+1, j, k), (i, j+1, k) and (i, j, k+1).
Examples:
Input: M = 1, N = 1, K = 1
Output: 1
Explanation: As the source and destination both are same, there is only one possible way to stay there.
Input: M = 2, N = 2, K = 2
Output: 6
Explanation: The possible paths are :
- (0, 0, 0) -> (0, 1, 0) -> (0, 1, 1) -> (1, 1, 1)
- (0, 0, 0) -> (0, 1, 0) -> (1, 1, 0) -> (1, 1, 1)
- (0, 0, 0) -> (1, 0, 0) -> (1, 1, 0) -> (1, 1, 1)
- (0, 0, 0) -> (1, 0, 0) -> (1, 0, 1) -> (1, 1, 1)
- (0, 0, 0) -> (0, 0, 1) -> (0, 1, 1) -> (1, 1, 1)
- (0, 0, 0) -> (0, 0, 1) -> (1, 0, 1) -> (1, 1, 1)
Approach: This problem can be solved by using dynamic programming. Follow the below steps, to solve this problem:
- Create a 3D array of size M*N*K, say dp and initialise dp[0][0][0] to 1.
- Use three nested loop where the outermost iterates from i = 0 to i < M, the innermost iterates from k = 0 to k < K and the middle one from j = 0 to j < N.
- Here, dp[i][j][k] indicates the number of paths from cell (0, 0, 0) to the cell (i, j, k).
- So, any cell(i, j, k), can be reached from only 3 other cells which are (i-1, j, k), (i, j-1, k) and (i, j, k-1).
- Therefore, the relation among the cells here is:
dp[i][j][k] = dp[i – 1][j][k] + dp[i][j – 1][k] + dp[i][j][k – 1]
- Fill the whole dp matrix using the above relation and then return dp[M-1][N-1][K-1] as the answer.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int numberOfWays( int M, int N, int K)
{
vector<vector<vector< int > > > dp(
M, vector<vector< int > >(
N, vector< int >(K)));
dp[0][0][0] = 1;
for ( int i = 0; i < M; ++i) {
for ( int j = 0; j < N; ++j) {
for ( int k = 0; k < K; ++k) {
if (i == 0 and j == 0
and k == 0) {
continue ;
}
dp[i][j][k] = 0;
if (i - 1 >= 0) {
dp[i][j][k] += dp[i - 1][j][k];
}
if (j - 1 >= 0) {
dp[i][j][k] += dp[i][j - 1][k];
}
if (k - 1 >= 0) {
dp[i][j][k] += dp[i][j][k - 1];
}
}
}
}
return dp[M - 1][N - 1][K - 1];
}
int main()
{
int M = 2, N = 2, K = 2;
cout << numberOfWays(M, N, K);
return 0;
}
|
Java
import java.io.*;
class GFG {
static int numberOfWays( int M, int N, int K)
{
int [][][] dp = new int [M][N][K];
dp[ 0 ][ 0 ][ 0 ] = 1 ;
for ( int i = 0 ; i < M; ++i) {
for ( int j = 0 ; j < N; ++j) {
for ( int k = 0 ; k < K; ++k) {
if (i == 0 && j == 0
&& k == 0 ) {
continue ;
}
dp[i][j][k] = 0 ;
if (i - 1 >= 0 ) {
dp[i][j][k] += dp[i - 1 ][j][k];
}
if (j - 1 >= 0 ) {
dp[i][j][k] += dp[i][j - 1 ][k];
}
if (k - 1 >= 0 ) {
dp[i][j][k] += dp[i][j][k - 1 ];
}
}
}
}
return dp[M - 1 ][N - 1 ][K - 1 ];
}
public static void main (String[] args)
{
int M = 2 , N = 2 , K = 2 ;
System.out.println(numberOfWays(M, N, K));
}
}
|
Python3
def numberOfWays(M, N, K):
dp = [[[ 0 for i in range (K)] for j in range (N)] for k in range (M)]
dp[ 0 ][ 0 ][ 0 ] = 1 ;
for i in range (M):
for j in range (N):
for k in range (K):
if (i = = 0 and j = = 0 and k = = 0 ):
continue ;
dp[i][j][k] = 0 ;
if (i - 1 > = 0 ):
dp[i][j][k] + = dp[i - 1 ][j][k];
if (j - 1 > = 0 ):
dp[i][j][k] + = dp[i][j - 1 ][k];
if (k - 1 > = 0 ):
dp[i][j][k] + = dp[i][j][k - 1 ];
return dp[M - 1 ][N - 1 ][K - 1 ];
M = 2
N = 2
K = 2 ;
print (numberOfWays(M, N, K));
|
C#
using System;
class GFG {
static int numberOfWays( int M, int N, int K)
{
int [, , ] dp = new int [M, N, K];
dp[0, 0, 0] = 1;
for ( int i = 0; i < M; ++i) {
for ( int j = 0; j < N; ++j) {
for ( int k = 0; k < K; ++k) {
if (i == 0 && j == 0 && k == 0) {
continue ;
}
dp[i, j, k] = 0;
if (i - 1 >= 0) {
dp[i, j, k] += dp[i - 1, j, k];
}
if (j - 1 >= 0) {
dp[i, j, k] += dp[i, j - 1, k];
}
if (k - 1 >= 0) {
dp[i, j, k] += dp[i, j, k - 1];
}
}
}
}
return dp[M - 1, N - 1, K - 1];
}
public static void Main( string [] args)
{
int M = 2, N = 2, K = 2;
Console.WriteLine(numberOfWays(M, N, K));
}
}
|
Javascript
<script>
const numberOfWays = (M, N, K) => {
let dp = new Array(M).fill(0).map(() => new Array(N).fill(0).map(() => new Array(K).fill(0)));
dp[0][0][0] = 1;
for (let i = 0; i < M; ++i) {
for (let j = 0; j < N; ++j) {
for (let k = 0; k < K; ++k) {
if (i == 0 && j == 0
&& k == 0) {
continue ;
}
dp[i][j][k] = 0;
if (i - 1 >= 0) {
dp[i][j][k] += dp[i - 1][j][k];
}
if (j - 1 >= 0) {
dp[i][j][k] += dp[i][j - 1][k];
}
if (k - 1 >= 0) {
dp[i][j][k] += dp[i][j][k - 1];
}
}
}
}
return dp[M - 1][N - 1][K - 1];
}
let M = 2, N = 2, K = 2;
document.write(numberOfWays(M, N, K));
</script>
|
Time Complexity: O(M*N*K)
Space Complexity: O(M*N*K)
Efficient approach : Optimize space complexity
In previous approach we can see that the dp[i][j][k] is depend upon dp[i – 1][j][k], dp[i][j – 1][k] and dp[i][j][k – 1] so we can convert 3d matric into current and previous 2d matrix where i-1 refer to previous and i refer to current.
Implantation steps :
- Create two 2d matrix refer to previous and current matrix.
- Initialize both matrix starting point with 1.
- Now the approach is same as the previous code but we have to only convert dp[i] to current and dp[i-1] to previous.
- At last return the answer
Implementation :
C++
#include <bits/stdc++.h>
using namespace std;
int numberOfWays( int M, int N, int K)
{
vector<vector< int > > curr(N, vector< int >(K, 0));
vector<vector< int > > prev(N, vector< int >(K, 0));
prev[0][0] = 1;
curr[0][0] = 1;
for ( int i = 0; i < M; ++i) {
for ( int j = 0; j < N; ++j) {
for ( int k = 0; k < K; ++k) {
if (i == 0 and j == 0 and k == 0) {
continue ;
}
curr[j][k] = 0;
if (i - 1 >= 0) {
curr[j][k] += prev[j][k];
}
if (j - 1 >= 0) {
curr[j][k] += curr[j - 1][k];
}
if (k - 1 >= 0) {
curr[j][k] += curr[j][k - 1];
}
}
}
prev = curr;
}
return curr[N - 1][K - 1];
}
int main()
{
int M = 2, N = 2, K = 2;
cout << numberOfWays(M, N, K);
return 0;
}
|
Java
public class Main {
public static int numberOfWays( int M, int N, int K)
{
int [][] curr = new int [N][K];
int [][] prev = new int [N][K];
prev[ 0 ][ 0 ] = 1 ;
curr[ 0 ][ 0 ] = 1 ;
for ( int i = 0 ; i < M; ++i) {
for ( int j = 0 ; j < N; ++j) {
for ( int k = 0 ; k < K; ++k) {
if (i == 0 && j == 0 && k == 0 ) {
continue ;
}
curr[j][k] = 0 ;
if (i - 1 >= 0 ) {
curr[j][k] += prev[j][k];
}
if (j - 1 >= 0 ) {
curr[j][k] += curr[j - 1 ][k];
}
if (k - 1 >= 0 ) {
curr[j][k] += curr[j][k - 1 ];
}
}
}
for ( int j = 0 ; j < N; j++) {
prev[j] = curr[j].clone();
}
}
return curr[N - 1 ][K - 1 ];
}
public static void main(String[] args)
{
int M = 2 , N = 2 , K = 2 ;
System.out.println(numberOfWays(M, N, K));
}
}
|
Python3
def numberOfWays(M, N, K):
curr = [[ 0 for _ in range (K)] for _ in range (N)]
prev = [[ 0 for _ in range (K)] for _ in range (N)]
prev[ 0 ][ 0 ] = 1
curr[ 0 ][ 0 ] = 1
for i in range (M):
for j in range (N):
for k in range (K):
if i = = 0 and j = = 0 and k = = 0 :
continue
curr[j][k] = 0
if i - 1 > = 0 :
curr[j][k] + = prev[j][k]
if j - 1 > = 0 :
curr[j][k] + = curr[j - 1 ][k]
if k - 1 > = 0 :
curr[j][k] + = curr[j][k - 1 ]
prev[j] = curr[j].copy()
return curr[N - 1 ][K - 1 ]
M, N, K = 2 , 2 , 2
print (numberOfWays(M, N, K))
|
Javascript
function numberOfWays(M, N, K) {
let curr = new Array(N);
let prev = new Array(N);
for (let i = 0; i < N; i++) {
curr[i] = new Array(K).fill(0);
prev[i] = new Array(K).fill(0);
}
prev[0][0] = 1;
curr[0][0] = 1;
for (let i = 0; i < M; i++) {
for (let j = 0; j < N; j++) {
for (let k = 0; k < K; k++) {
if (i === 0 && j === 0 && k === 0) {
continue ;
}
curr[j][k] = 0;
if (i - 1 >= 0) {
curr[j][k] += prev[j][k];
}
if (j - 1 >= 0) {
curr[j][k] += curr[j - 1][k];
}
if (k - 1 >= 0) {
curr[j][k] += curr[j][k - 1];
}
}
}
for (let j = 0; j < N; j++) {
prev[j] = [...curr[j]];
}
}
return curr[N - 1][K - 1];
}
const M = 2;
const N = 2;
const K = 2;
console.log(numberOfWays(M, N, K));
|
C#
using System;
public class MainClass {
public static int NumberOfWays( int M, int N, int K)
{
int [, ] curr = new int [N, K];
int [, ] prev = new int [N, K];
prev[0, 0] = 1;
curr[0, 0] = 1;
for ( int i = 0; i < M; ++i) {
for ( int j = 0; j < N; ++j) {
for ( int k = 0; k < K; ++k) {
if (i == 0 && j == 0 && k == 0) {
continue ;
}
curr[j, k] = 0;
if (i - 1 >= 0) {
curr[j, k] += prev[j, k];
}
if (j - 1 >= 0) {
curr[j, k] += curr[j - 1, k];
}
if (k - 1 >= 0) {
curr[j, k] += curr[j, k - 1];
}
}
}
prev = curr.Clone() as int [, ];
}
return curr[N - 1, K - 1];
}
public static void Main( string [] args)
{
int M = 2, N = 2, K = 2;
Console.WriteLine(NumberOfWays(M, N, K));
}
}
|
Output :
6
Time Complexity: O(M*N*K)
Auxiliary Space: O(N*K)
Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!
Last Updated :
04 Apr, 2023
Like Article
Save Article