Number of paths with exactly k coins (original) (raw)
Given a matrix **mat[][] where each cell contains a certain number of coins, and an integer **k, count the total number of **distinct paths from the top-left cell to the bottom-right cell such that the sum of coins collected along the path is exactly k.
From any cell (i, j), we can move either downward (i + 1, j) or rightward (i, j + 1).
**Example:
**Input: k = 12, mat[][] = [[1, 2, 3],
[4, 6, 5],
[3, 2, 1]]
**Output: 2
**Explanation: There are two paths with 12 coins
1 -> 2 -> 6 -> 2 -> 1
1 -> 2 -> 3 -> 5 -> 1**Input: k = 16, mat[][] = [[1, 2, 3],
[4, 6, 5],
[9, 8, 7]]
**Output: 0
**Explanation: There are no possible paths that lead to sum=16
Table of Content
- [Naive Approach] Using Recursion - O(2^(m+n)) Time and O(m+n) Auxiliary Space
- [Better Approach 1] Using Top Down (Memoization) - O(m*n*k) Time and O(n*m*k) Space
- [Better Approach 2] Using Bottom Up (Tabulation) - O(n*m*k) Time and O(n*m*k) Space
- [Expected Approach] Using Space Optimization - O(n*m*k) Time and O(m*k) Space
[Naive Approach] Using Recursion - O(2(m+n)) Time and O(m+n) Auxiliary Space
The idea is to use recursion because we need to explore all possible paths from the top-left cell of the matrix to the bottom-right cell.
At each step, we can move:
- Downward - from cell (i, j) to (i + 1, j)
- Rightward - from cell (i, j) to (i, j + 1)
As we move, we keep adding the number of coins in the current cell to our running total. Whenever we reach the bottom-right cell, we check whether this total sum is exactly equal to k. If it matches k, we count this path as a valid path. If not, we simply return without counting it.
C++ `
//Driver Code Starts #include #include using namespace std; //Driver Code Ends
// Recursive function to count paths int pathCountRec(vector<vector>& mat, int i, int j, int k) { int n = mat.size(); int m = mat[0].size();
// Base conditions
if (i >= n || j >= m) return 0;
// Sum exceeded then return
if (k < 0) return 0;
// Reached destination cell
if (i == n - 1 && j == m - 1)
return (k == mat[i][j]);
// Move either right or down and reduce the required sum
return pathCountRec(mat, i + 1, j, k - mat[i][j]) +
pathCountRec(mat, i, j + 1, k - mat[i][j]);}
int numberOfPath(vector<vector>& mat, int k) { return pathCountRec(mat, 0, 0, k); }
//Driver Code Starts int main() { int k = 12; vector<vector> mat = { {1, 2, 3}, {4, 6, 5}, {3, 2, 1} };
cout << numberOfPath(mat, k);
return 0;}
//Driver Code Ends
Java
//Driver Code Starts class GFG { //Driver Code Ends
// Recursive function to count paths
static int pathCountRec(int[][] mat, int i, int j, int k) {
int n = mat.length;
int m = mat[0].length;
// Base conditions
if (i >= n || j >= m)
return 0;
// Sum exceeded then return
if (k < 0)
return 0;
// Reached destination cell
if (i == n - 1 && j == m - 1)
return (k == mat[i][j]) ? 1 : 0;
// Move either right or down and reduce the required sum
return pathCountRec(mat, i + 1, j, k - mat[i][j]) +
pathCountRec(mat, i, j + 1, k - mat[i][j]);
}
static int numberOfPath(int[][] mat, int k) {
return pathCountRec(mat, 0, 0, k);
}//Driver Code Starts public static void main(String[] args) { int k = 12; int[][] mat = { {1, 2, 3}, {4, 6, 5}, {3, 2, 1} };
System.out.println(numberOfPath(mat, k));
}}
//Driver Code Ends
Python
Recursive function to count paths
def pathCountRec(mat, i, j, k): n = len(mat) m = len(mat[0])
# Base conditions
if i >= n or j >= m:
return 0
# Sum exceeded then return
if k < 0:
return 0
# Reached destination cell
if i == n - 1 and j == m - 1:
return 1 if k == mat[i][j] else 0
# Move either right or down and reduce the required sum
return (pathCountRec(mat, i + 1, j, k - mat[i][j]) +
pathCountRec(mat, i, j + 1, k - mat[i][j]))def numberOfPath(mat, k): return pathCountRec(mat, 0, 0, k)
if name == "main": #Driver Code Starts k = 12 mat = [ [1, 2, 3], [4, 6, 5], [3, 2, 1] ]
print(numberOfPath(mat, k))#Driver Code Ends
C#
//Driver Code Starts using System;
class GFG { //Driver Code Ends
// Recursive function to count paths
static int pathCountRec(int[,] mat, int i, int j, int k) {
int n = mat.GetLength(0);
int m = mat.GetLength(1);
// Base conditions
if (i >= n || j >= m)
return 0;
// Sum exceeded then return
if (k < 0)
return 0;
// Reached destination cell
if (i == n - 1 && j == m - 1)
return (k == mat[i, j]) ? 1 : 0;
// Move either right or down and reduce the required sum
return pathCountRec(mat, i + 1, j, k - mat[i, j]) +
pathCountRec(mat, i, j + 1, k - mat[i, j]);
}
static int numberOfPath(int[,] mat, int k) {
return pathCountRec(mat, 0, 0, k);
}//Driver Code Starts static void Main() { int k = 12; int[,] mat = { {1, 2, 3}, {4, 6, 5}, {3, 2, 1} };
Console.WriteLine(numberOfPath(mat, k));
}}
//Driver Code Ends
JavaScript
// Recursive function to count paths function pathCountRec(mat, i, j, k) { const n = mat.length; const m = mat[0].length;
// Base conditions
if (i >= n || j >= m) return 0;
// Sum exceeded then return
if (k < 0) return 0;
// Reached destination cell
if (i === n - 1 && j === m - 1)
return (k === mat[i][j]) ? 1 : 0;
// Move either right or down and reduce the required sum
return pathCountRec(mat, i + 1, j, k - mat[i][j]) +
pathCountRec(mat, i, j + 1, k - mat[i][j]);}
function numberOfPath(mat, k) { return pathCountRec(mat, 0, 0, k); }
// Driver code //Driver Code Starts const k = 12; const mat = [ [1, 2, 3], [4, 6, 5], [3, 2, 1] ];
console.log(numberOfPath(mat, k));
//Driver Code Ends
`
[Better Approach 1] Using Top Down (Memoization) - O(m*n*k) Time and O(n*m*k) Space
In the recursive approach, there are many overlapping subproblems that get solved repeatedly, which increases the time complexity.
To handle this issue, we use memoization.
We create a 3D DP array memo[n][m][k+1], because in the recursive function there are three parameters that keep changing:
- i: current row index
- j: current column index
- k: remaining sum
So, memo[i][j][k] stores the number of valid paths starting from cell (i, j) when the remaining sum is k.
Whenever we encounter the same subproblem again, we first check in the memo table whether it has already been solved. If it has, we directly return the stored result instead of recomputing it.
C++ `
//Driver Code Starts #include #include using namespace std; //Driver Code Ends
// Recursive function with memoization int pathCountRec(vector<vector>& mat, int i, int j, int k, vector<vector<vector>>& dp) { int n = mat.size(); int m = mat[0].size();
if (i >= n || j >= m) return 0;
// Sum exceeded
if (k < 0) return 0;
if (i == n - 1 && j == m - 1)
return (k == mat[i][j]);
// If already computed, return stored value
if (dp[i][j][k] != -1)
return dp[i][j][k];
// Explore down and right moves
int down = pathCountRec(mat, i + 1, j, k - mat[i][j], dp);
int right = pathCountRec(mat, i, j + 1, k - mat[i][j], dp);
return dp[i][j][k] = down + right;}
int numberOfPath(vector<vector>& mat, int k) { int n = mat.size(); int m = mat[0].size();
vector<vector<vector<int>>> dp(
n, vector<vector<int>>(m, vector<int>(k + 1, -1))
);
return pathCountRec(mat, 0, 0, k, dp);}
//Driver Code Starts int main() { int k = 12; vector<vector> mat = { {1, 2, 3}, {4, 6, 5}, {3, 2, 1} };
cout << numberOfPath(mat, k);
return 0;}
//Driver Code Ends
Java
//Driver Code Starts import java.util.Arrays;
class GFG { //Driver Code Ends
// Recursive function with memoization
static int pathCountRec(int[][] mat, int i, int j, int k, int[][][] dp) {
int n = mat.length;
int m = mat[0].length;
if (i >= n || j >= m)
return 0;
// Sum exceeded
if (k < 0)
return 0;
if (i == n - 1 && j == m - 1)
return (k == mat[i][j]) ? 1 : 0;
// If already computed, return stored value
if (dp[i][j][k] != -1)
return dp[i][j][k];
// Explore down and right moves
int down = pathCountRec(mat, i + 1, j, k - mat[i][j], dp);
int right = pathCountRec(mat, i, j + 1, k - mat[i][j], dp);
return dp[i][j][k] = down + right;
}
static int numberOfPath(int[][] mat, int k) {
int n = mat.length;
int m = mat[0].length;
int[][][] dp = new int[n][m][k + 1];
for (int[][] arr2D : dp)
for (int[] arr1D : arr2D)
Arrays.fill(arr1D, -1);
return pathCountRec(mat, 0, 0, k, dp);
}//Driver Code Starts public static void main(String[] args) { int k = 12; int[][] mat = { {1, 2, 3}, {4, 6, 5}, {3, 2, 1} };
System.out.println(numberOfPath(mat, k));
}}
//Driver Code Ends
Python
Recursive function with memoization
def pathCountRec(mat, i, j, k, dp): n = len(mat) m = len(mat[0])
if i >= n or j >= m:
return 0
# Sum exceeded
if k < 0:
return 0
if i == n - 1 and j == m - 1:
return 1 if k == mat[i][j] else 0
# If already computed, return stored value
if dp[i][j][k] != -1:
return dp[i][j][k]
# Explore down and right moves
down = pathCountRec(mat, i + 1, j, k - mat[i][j], dp)
right = pathCountRec(mat, i, j + 1, k - mat[i][j], dp)
dp[i][j][k] = down + right
return dp[i][j][k]def numberOfPath(mat, k): n = len(mat) m = len(mat[0])
dp = [[[-1 for _ in range(k + 1)] for _ in range(m)] for _ in range(n)]
return pathCountRec(mat, 0, 0, k, dp)#Driver Code Starts if name == "main": k = 12 mat = [ [1, 2, 3], [4, 6, 5], [3, 2, 1] ]
print(numberOfPath(mat, k))#Driver Code Ends
C#
//Driver Code Starts using System;
class GFG { //Driver Code Ends
// Recursive function with memoization
static int pathCountRec(int[,] mat, int i, int j, int k, int[,,] dp) {
int n = mat.GetLength(0);
int m = mat.GetLength(1);
if (i >= n || j >= m)
return 0;
// Sum exceeded
if (k < 0)
return 0;
if (i == n - 1 && j == m - 1)
return (k == mat[i, j]) ? 1 : 0;
// If already computed, return stored value
if (dp[i, j, k] != -1)
return dp[i, j, k];
// Explore down and right moves
int down = pathCountRec(mat, i + 1, j, k - mat[i, j], dp);
int right = pathCountRec(mat, i, j + 1, k - mat[i, j], dp);
return dp[i, j, k] = down + right;
}
static int numberOfPath(int[,] mat, int k) {
int n = mat.GetLength(0);
int m = mat.GetLength(1);
int[,,] dp = new int[n, m, k + 1];
for (int x = 0; x < n; x++)
for (int y = 0; y < m; y++)
for (int z = 0; z <= k; z++)
dp[x, y, z] = -1;
return pathCountRec(mat, 0, 0, k, dp);
}//Driver Code Starts static void Main() { int k = 12; int[,] mat = { {1, 2, 3}, {4, 6, 5}, {3, 2, 1} };
Console.WriteLine(numberOfPath(mat, k));
}}
//Driver Code Ends
JavaScript
// Recursive function with memoization function pathCountRec(mat, i, j, k, dp) { const n = mat.length; const m = mat[0].length;
if (i >= n || j >= m)
return 0;
// Sum exceeded
if (k < 0)
return 0;
if (i === n - 1 && j === m - 1)
return (k === mat[i][j]) ? 1 : 0;
// If already computed, return stored value
if (dp[i][j][k] !== -1)
return dp[i][j][k];
// Explore down and right moves
const down = pathCountRec(mat, i + 1, j, k - mat[i][j], dp);
const right = pathCountRec(mat, i, j + 1, k - mat[i][j], dp);
dp[i][j][k] = down + right;
return dp[i][j][k];}
function numberOfPath(mat, k) { const n = mat.length; const m = mat[0].length;
const dp = Array.from({ length: n }, () =>
Array.from({ length: m }, () => Array(k + 1).fill(-1))
);
return pathCountRec(mat, 0, 0, k, dp);}
// Driver code //Driver Code Starts const k = 12; const mat = [ [1, 2, 3], [4, 6, 5], [3, 2, 1] ];
console.log(numberOfPath(mat, k));
//Driver Code Ends
`
[Better Approach 2] Using Bottom Up (Tabulation) - O(n*m*k) Time and O(n*m*k) Space
In this approach, instead of using recursion, we use bottom-up to build the solution iteratively.
We create a 3D DP array dp[n][m][k+1], where each entry dp[i][j][sum] represents the number of ways to reach cell (i, j) with a total sum of coins equal to sum.
We start from the top-left cell as our base case since it’s the starting point. So, if mat[0][0] ≤ k, we set dp[0][0][mat[0][0]] = 1, meaning there is exactly one valid way to reach (0, 0) with the sum equal to the value of that cell; otherwise, it’s not valid since the sum already exceeds k.
To fill the rest of the table, we use the relation:
dp[i][j][sum] = dp[i-1][j][sum - mat[i][j]] + dp[i][j-1][sum - mat[i][j]].
This means that to reach cell (i, j) with a total sum sum, we can either come from the top cell (i-1, j) or from the left cell (i, j-1) with the remaining sum sum - mat[i][j].
We then iterate through all cells (i, j) and all possible sums from 0 to k to fill the DP table.
C++ `
//Driver Code Starts #include #include using namespace std; //Driver Code Ends
int numberOfPath(vector<vector>& mat, int k) { int n = mat.size(), m = mat[0].size(); vector<vector<vector>> dp(n, vector<vector>(m, vector(k + 1, 0)));
// Base case
if (mat[0][0] <= k)
dp[0][0][mat[0][0]] = 1;
// Build table iteratively
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
for (int sum = 0; sum <= k; sum++) {
if (sum - mat[i][j] >= 0) {
// from top
if (i > 0) dp[i][j][sum] += dp[i - 1][j][sum - mat[i][j]];
// from left
if (j > 0) dp[i][j][sum] += dp[i][j - 1][sum - mat[i][j]];
}
}
}
}
//total ways to reach bottom-right with sum = k
return dp[n - 1][m - 1][k];}
//Driver Code Starts int main() { int k = 12; vector<vector> mat = { {1, 2, 3}, {4, 6, 5}, {3, 2, 1} }; cout << numberOfPath(mat, k); return 0; }
//Driver Code Ends
Java
//Driver Code Starts import java.util.Arrays;
class GFG { //Driver Code Ends
static int numberOfPath(int[][] mat, int k) {
int n = mat.length, m = mat[0].length;
int[][][] dp = new int[n][m][k + 1];
// Base case
if (mat[0][0] <= k)
dp[0][0][mat[0][0]] = 1;
// Build table iteratively
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
for (int sum = 0; sum <= k; sum++) {
if (sum - mat[i][j] >= 0) {
// from top
if (i > 0)
dp[i][j][sum] += dp[i - 1][j][sum - mat[i][j]];
// from left
if (j > 0)
dp[i][j][sum] += dp[i][j - 1][sum - mat[i][j]];
}
}
}
}
// total ways to reach bottom-right with sum = k
return dp[n - 1][m - 1][k];
}//Driver Code Starts public static void main(String[] args) { int k = 12; int[][] mat = { {1, 2, 3}, {4, 6, 5}, {3, 2, 1} };
System.out.println(numberOfPath(mat, k));
}}
//Driver Code Ends
Python
def numberOfPath(mat, k): n = len(mat) m = len(mat[0]) dp = [[[0 for _ in range(k + 1)] for _ in range(m)] for _ in range(n)]
# Base case
if mat[0][0] <= k:
dp[0][0][mat[0][0]] = 1
# Build table iteratively
for i in range(n):
for j in range(m):
for sum in range(k + 1):
if sum - mat[i][j] >= 0:
# from top
if i > 0:
dp[i][j][sum] += dp[i - 1][j][sum - mat[i][j]]
# from left
if j > 0:
dp[i][j][sum] += dp[i][j - 1][sum - mat[i][j]]
# total ways to reach bottom-right with sum = k
return dp[n - 1][m - 1][k]#Driver Code Starts if name == "main": k = 12 mat = [ [1, 2, 3], [4, 6, 5], [3, 2, 1] ] print(numberOfPath(mat, k))
#Driver Code Ends
C#
//Driver Code Starts using System;
class GFG { //Driver Code Ends
static int numberOfPath(int[,] mat, int k) {
int n = mat.GetLength(0), m = mat.GetLength(1);
int[,,] dp = new int[n, m, k + 1];
// Base case
if (mat[0, 0] <= k)
dp[0, 0, mat[0, 0]] = 1;
// Build table iteratively
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
for (int sum = 0; sum <= k; sum++) {
if (sum - mat[i, j] >= 0) {
// from top
if (i > 0)
dp[i, j, sum] += dp[i - 1, j, sum - mat[i, j]];
// from left
if (j > 0)
dp[i, j, sum] += dp[i, j - 1, sum - mat[i, j]];
}
}
}
}
// total ways to reach bottom-right with sum = k
return dp[n - 1, m - 1, k];
}//Driver Code Starts static void Main() { int k = 12; int[,] mat = { {1, 2, 3}, {4, 6, 5}, {3, 2, 1} };
Console.WriteLine(numberOfPath(mat, k));
}}
//Driver Code Ends
JavaScript
function numberOfPath(mat, k) { const n = mat.length; const m = mat[0].length;
// create 3D dp array
const dp = Array.from({ length: n }, () =>
Array.from({ length: m }, () => Array(k + 1).fill(0))
);
// Base case
if (mat[0][0] <= k)
dp[0][0][mat[0][0]] = 1;
// Build table iteratively
for (let i = 0; i < n; i++) {
for (let j = 0; j < m; j++) {
for (let sum = 0; sum <= k; sum++) {
if (sum - mat[i][j] >= 0) {
// from top
if (i > 0)
dp[i][j][sum] += dp[i - 1][j][sum - mat[i][j]];
// from left
if (j > 0)
dp[i][j][sum] += dp[i][j - 1][sum - mat[i][j]];
}
}
}
}
// total ways to reach bottom-right with sum = k
return dp[n - 1][m - 1][k];}
// Driver Code //Driver Code Starts const k = 12; const mat = [ [1, 2, 3], [4, 6, 5], [3, 2, 1] ];
console.log(numberOfPath(mat, k));
//Driver Code Ends
`
[Expected Approach] Using Space Optimization - O(n*m*k) Time and O(m*k) Space
In the previous approach, we used a 3D DP table dp[n][m][k+1]. But if we observe carefully, to calculate the value for the current row, we only need the values from the previous row and the current row itself.
So, instead of keeping the entire 3D table, we can store only two 2D arrays:
- prev[m][k+1] - represents results of the previous row
- curr[m][k+1] - represents results for the current row being calculated
After finishing one row, we simply copy curr to prev and reuse the same arrays for the next iteration.
C++ `
//Driver Code Starts #include #include using namespace std; //Driver Code Ends
int numberOfPath(vector<vector>& mat, int k) { int n = mat.size(), m = mat[0].size();
// Use only two 2D arrays for space optimization
vector<vector<int>> prev(m, vector<int>(k + 1, 0));
vector<vector<int>> curr(m, vector<int>(k + 1, 0));
// Build DP table iteratively
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
for (int sum = 0; sum <= k; sum++) {
// Base case
if (i == 0 && j == 0) {
// Only one way if sum matches cell value
curr[j][sum] = (sum == mat[0][0]);
continue;
}
curr[j][sum] = 0;
if (sum - mat[i][j] >= 0) {
// from top
if (i > 0) curr[j][sum] += prev[j][sum - mat[i][j]];
// from left
if (j > 0) curr[j][sum] += curr[j - 1][sum - mat[i][j]];
}
}
}
// Move current row to previous row
prev = curr;
}
// Total ways to reach bottom-right with sum = k
return prev[m - 1][k];}
//Driver Code Starts int main() { int k = 12; vector<vector> mat = { {1, 2, 3}, {4, 6, 5}, {3, 2, 1} };
cout << numberOfPath(mat, k);
return 0;}
//Driver Code Ends
Java
//Driver Code Starts import java.util.Arrays;
class GFG { //Driver Code Ends
static int numberOfPath(int[][] mat, int k) {
int n = mat.length, m = mat[0].length;
// Use only two 2D arrays for space optimization
int[][] prev = new int[m][k + 1];
int[][] curr = new int[m][k + 1];
// Build DP table iteratively
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
for (int sum = 0; sum <= k; sum++) {
// Base case
if (i == 0 && j == 0) {
// Only one way if sum matches cell value
curr[j][sum] = (sum == mat[0][0]) ? 1 : 0;
continue;
}
curr[j][sum] = 0;
if (sum - mat[i][j] >= 0) {
// from top
if (i > 0)
curr[j][sum] += prev[j][sum - mat[i][j]];
// from left
if (j > 0)
curr[j][sum] += curr[j - 1][sum - mat[i][j]];
}
}
}
// Move current row to previous row
for (int j = 0; j < m; j++)
prev[j] = Arrays.copyOf(curr[j], curr[j].length);
}
// Total ways to reach bottom-right with sum = k
return prev[m - 1][k];
}//Driver Code Starts public static void main(String[] args) { int k = 12; int[][] mat = { {1, 2, 3}, {4, 6, 5}, {3, 2, 1} };
System.out.println(numberOfPath(mat, k));
}}
//Driver Code Ends
Python
def numberOfPath(mat, k): n = len(mat) m = len(mat[0])
# Use only two 2D arrays for space optimization
prev = [[0] * (k + 1) for _ in range(m)]
curr = [[0] * (k + 1) for _ in range(m)]
# Build DP table iteratively
for i in range(n):
for j in range(m):
for sum_ in range(k + 1):
# Base case
if i == 0 and j == 0:
# Only one way if sum matches cell value
curr[j][sum_] = 1 if sum_ == mat[0][0] else 0
continue
curr[j][sum_] = 0
if sum_ - mat[i][j] >= 0:
# from top
if i > 0:
curr[j][sum_] += prev[j][sum_ - mat[i][j]]
# from left
if j > 0:
curr[j][sum_] += curr[j - 1][sum_ - mat[i][j]]
# Move current row to previous row
prev = [row[:] for row in curr]
# Total ways to reach bottom-right with sum = k
return prev[m - 1][k]#Driver Code Starts if name == "main": k = 12 mat = [ [1, 2, 3], [4, 6, 5], [3, 2, 1] ]
print(numberOfPath(mat, k))#Driver Code Ends
C#
//Driver Code Starts using System;
class GFG { //Driver Code Ends
static int numberOfPath(int[,] mat, int k) {
int n = mat.GetLength(0);
int m = mat.GetLength(1);
// Use only two 2D arrays for space optimization
int[,] prev = new int[m, k + 1];
int[,] curr = new int[m, k + 1];
// Build DP table iteratively
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
for (int sum = 0; sum <= k; sum++) {
// Base case
if (i == 0 && j == 0) {
// Only one way if sum matches cell value
curr[j, sum] = (sum == mat[0, 0]) ? 1 : 0;
continue;
}
curr[j, sum] = 0;
if (sum - mat[i, j] >= 0) {
// from top
if (i > 0) curr[j, sum] += prev[j, sum - mat[i, j]];
// from left
if (j > 0) curr[j, sum] += curr[j - 1, sum - mat[i, j]];
}
}
}
// Move current row to previous row
for (int j = 0; j < m; j++)
for (int sum = 0; sum <= k; sum++)
prev[j, sum] = curr[j, sum];
}
// Total ways to reach bottom-right with sum = k
return prev[m - 1, k];
}//Driver Code Starts static void Main() { int k = 12; int[,] mat = { {1, 2, 3}, {4, 6, 5}, {3, 2, 1} };
Console.WriteLine(numberOfPath(mat, k));
}}
//Driver Code Ends
JavaScript
function numberOfPath(mat, k) { const n = mat.length; const m = mat[0].length;
// Use only two 2D arrays for space optimization
let prev = Array.from({ length: m }, () => Array(k + 1).fill(0));
let curr = Array.from({ length: m }, () => Array(k + 1).fill(0));
// Build DP table iteratively
for (let i = 0; i < n; i++) {
for (let j = 0; j < m; j++) {
for (let sum = 0; sum <= k; sum++) {
// Base case
if (i === 0 && j === 0) {
// Only one way if sum matches cell value
curr[j][sum] = (sum === mat[0][0]) ? 1 : 0;
continue;
}
curr[j][sum] = 0;
if (sum - mat[i][j] >= 0) {
// from top
if (i > 0) curr[j][sum] += prev[j][sum - mat[i][j]];
// from left
if (j > 0) curr[j][sum] += curr[j - 1][sum - mat[i][j]];
}
}
}
// Move current row to previous row
prev = curr.map(row => [...row]);
}
// Total ways to reach bottom-right with sum = k
return prev[m - 1][k];}
// Driver Code //Driver Code Starts const k = 12; const mat = [ [1, 2, 3], [4, 6, 5], [3, 2, 1] ];
console.log(numberOfPath(mat, k));
//Driver Code Ends
`