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 20using namespace std;// 3d array to store// states of dpint dp[n][n][maxV];// Array to determine whether// a state has been solved beforeint v[n][n][maxV];// Function to return the count of required pathsint 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 codeint 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 approachclass 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 approachn = 3maxV = 20# 3d array to store states of dpdp = [[[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 beforev = [[[0 for i in range(maxV)] for i in range(n)] for i in range(n)]# Function to return# the count of required pathsdef 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 codearr = [[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 approachvar n = 3;var maxV = 20;// 3d array to store// states of dpvar 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 beforefor(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 pathsfunction 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 codevar 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!
