Number of paths with exactly k coins

Last Updated : 6 Nov, 2025

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

Try It Yourself
redirect icon

[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 <iostream>
#include<vector>
using namespace std;
//Driver Code Ends


// Recursive function to count paths 
int pathCountRec(vector<vector<int>>& 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<int>>& mat, int k) {
    return pathCountRec(mat, 0, 0, k);
}


//Driver Code Starts
int main() {
    int k = 12;
    vector<vector<int>> 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

Output
2

[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 <iostream>
#include <vector>
using namespace std;
//Driver Code Ends


// Recursive function with memoization
int pathCountRec(vector<vector<int>>& mat, int i, int j, int k,
                 vector<vector<vector<int>>>& 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<int>>& 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<int>> 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

Output
2

[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 <iostream>
#include <vector>
using namespace std;
//Driver Code Ends


int numberOfPath(vector<vector<int>>& mat, int k) {
    int n = mat.size(), m = mat[0].size();
    vector<vector<vector<int>>> dp(n, vector<vector<int>>(m, vector<int>(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<int>> 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

Output
2

[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 <iostream>
#include <vector>
using namespace std;
//Driver Code Ends


int numberOfPath(vector<vector<int>>& 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<int>> 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

Output
2


Comment