Given an N * N matrix arr[][] consisting of non-negative integers, the task is to find the number of ways to reach arr[N – 1][N – 1] with a non-zero AND value starting from the arr[0][0] by going down or right in every move. Whenever a cell arr[i][j] is reached, ‘AND’ value is updated as currentVal & arr[i][j].
Examples:
Input: arr[][] = {
{1, 1, 1},
{1, 1, 1},
{1, 1, 1}}
Output: 6
All the paths will give non-zero and value.
Thus, number of ways equals 6.
Input: arr[][] = {
{1, 1, 2},
{1, 2, 1},
{2, 1, 1}}
Output: 0
Approach: This problem can be solved using dynamic programming. First, we need to decide the states of the DP. For every cell arr[i][j] and a number X, we will store the number of ways to reach the arr[N – 1][N – 1] from arr[i][j] with non-zero AND where X is the AND value of path till now. Thus, our solution will use 3-dimensional dynamic programming, two for the coordinates of the cells and one for X.
The required recurrence relation is:
dp[i][j][X] = dp[i][j + 1][X & arr[i][j]] + dp[i + 1][j][X & arr[i][j]]
Below is the implementation of the above approach:
C++
// C++ implementation of the approach #include <bits/stdc++.h> #define n 3 #define maxV 20 using namespace std; // 3d array to store // states of dp int dp[n][n][maxV]; // Array to determine whether // a state has been solved before int v[n][n][maxV]; // Function to return the count of required paths int countWays( int i, int j, int x, int arr[][n]) { // Base cases if (i == n || j == n) return 0; x = (x & arr[i][j]); if (x == 0) return 0; if (i == n - 1 && j == n - 1) return 1; // If a state has been solved before // it won't be evaluated again if (v[i][j][x]) return dp[i][j][x]; v[i][j][x] = 1; // Recurrence relation dp[i][j][x] = countWays(i + 1, j, x, arr) + countWays(i, j + 1, x, arr); return dp[i][j][x]; } // Driver code int main() { int arr[n][n] = { { 1, 2, 1 }, { 1, 1, 0 }, { 2, 1, 1 } }; cout << countWays(0, 0, arr[0][0], arr); return 0; } |
Java
// Java implementation of the approach class GFG { static int n = 3 ; static int maxV = 20 ; // 3d array to store // states of dp static int [][][] dp = new int [n][n][maxV]; // Array to determine whether // a state has been solved before static int [][][] v = new int [n][n][maxV]; // Function to return the count of required paths static int countWays( int i, int j, int x, int arr[][]) { // Base cases if (i == n || j == n) { return 0 ; } x = (x & arr[i][j]); if (x == 0 ) { return 0 ; } if (i == n - 1 && j == n - 1 ) { return 1 ; } // If a state has been solved before // it won't be evaluated again if (v[i][j][x] == 1 ) { return dp[i][j][x]; } v[i][j][x] = 1 ; // Recurrence relation dp[i][j][x] = countWays(i + 1 , j, x, arr) + countWays(i, j + 1 , x, arr); return dp[i][j][x]; } // Driver code public static void main(String[] args) { int arr[][] = { { 1 , 2 , 1 }, { 1 , 1 , 0 }, { 2 , 1 , 1 } }; System.out.println(countWays( 0 , 0 , arr[ 0 ][ 0 ], arr)); } } // This code contributed by Rajput-Ji |
Python3
# Python3 implementation of the approach n = 3 maxV = 20 # 3d array to store states of dp dp = [[[ 0 for i in range (maxV)] for i in range (n)] for i in range (n)] # Array to determine whether # a state has been solved before v = [[[ 0 for i in range (maxV)] for i in range (n)] for i in range (n)] # Function to return # the count of required paths def countWays(i, j, x, arr): # Base cases if (i = = n or j = = n): return 0 x = (x & arr[i][j]) if (x = = 0 ): return 0 if (i = = n - 1 and j = = n - 1 ): return 1 # If a state has been solved before # it won't be evaluated again if (v[i][j][x]): return dp[i][j][x] v[i][j][x] = 1 # Recurrence relation dp[i][j][x] = countWays(i + 1 , j, x, arr) + \ countWays(i, j + 1 , x, arr); return dp[i][j][x] # Driver code arr = [[ 1 , 2 , 1 ], [ 1 , 1 , 0 ], [ 2 , 1 , 1 ]] print (countWays( 0 , 0 , arr[ 0 ][ 0 ], arr)) # This code is contributed by Mohit Kumar |
C#
// C# implementation of the approach using System; class GFG { static int n = 3; static int maxV = 20; // 3d array to store // states of dp static int [,,] dp = new int [n, n, maxV]; // Array to determine whether // a state has been solved before static int [,,] v = new int [n, n, maxV]; // Function to return the count of required paths static int countWays( int i, int j, int x, int [,]arr) { // Base cases if (i == n || j == n) { return 0; } x = (x & arr[i, j]); if (x == 0) { return 0; } if (i == n - 1 && j == n - 1) { return 1; } // If a state has been solved before // it won't be evaluated again if (v[i, j, x] == 1) { return dp[i, j, x]; } v[i, j, x] = 1; // Recurrence relation dp[i, j, x] = countWays(i + 1, j, x, arr) + countWays(i, j + 1, x, arr); return dp[i, j, x]; } // Driver code public static void Main() { int [,]arr = { { 1, 2, 1 }, { 1, 1, 0 }, { 2, 1, 1 } }; Console.WriteLine(countWays(0, 0, arr[0,0], arr)); } } // This code is contributed by AnkitRai01 |
Javascript
<script> // Javascript implementation of the approach var n = 3; var maxV = 20; // 3d array to store // states of dp var dp = new Array(n); for ( var i = 0; i<n; i++) { dp[i] = new Array(n); for ( var j =0; j<n;j++) { dp[i][j] = new Array(maxV); } } var v = new Array(n); // Array to determine whether // a state has been solved before for ( var i = 0; i<n; i++) { v[i] = new Array(n); for ( var j =0; j<n;j++) { v[i][j] = new Array(maxV); } } // Function to return the count of required paths function countWays(i, j, x, arr) { // Base cases if (i == n || j == n) return 0; x = (x & arr[i][j]); if (x == 0) return 0; if (i == n - 1 && j == n - 1) return 1; // If a state has been solved before // it won't be evaluated again if (v[i][j][x]) return dp[i][j][x]; v[i][j][x] = 1; // Recurrence relation dp[i][j][x] = countWays(i + 1, j, x, arr) + countWays(i, j + 1, x, arr); return dp[i][j][x]; } // Driver code var arr = [ [ 1, 2, 1 ], [ 1, 1, 0 ], [ 2, 1, 1 ] ]; document.write( countWays(0, 0, arr[0][0], arr)); </script> |
1
Time Complexity: O(n2)
Auxiliary Space: O(n4 * maxV)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!