Open In App

Gold Mine Problem

Last Updated : 08 Jul, 2025
Comments
Improve
Suggest changes
188 Likes
Like
Report

Given a gold mine represented as a 2d matrix mat[][], where each cell contains a positive integer indicating the amount of gold (in tons) available in that field. The miner can start from any row in the first column. From any cell, the miner is allowed to move in one of the following three directions:

  • Diagonally up-right.
  • Directly right.
  • Diagonally down-right.

The miner continues moving in this way until reaching the last column or until no further move is possible. Find the maximum amount of gold the miner can collect following these rules.

Examples: 

Input: mat[][] = [[1, 3, 3],
[2, 1, 4],
[0, 6, 4]]
Output: 12
Explanation: The miner starts from the second row of the first column (collecting 2 tons of gold), moves to the third row of the second column (collecting 6 tons of gold), and then to the second row of the third column (collecting 4 tons of gold), for a total of 2 + 6 + 4 = 12 tons of gold collected.

Input: mat[][] = [[1, 3, 1, 5],
[2, 2, 4, 1],
[5, 0, 2, 3],
[0, 6, 1, 2]];
Output: 16
Explanation: The miner starts from the third row of the first column (collecting 5 tons of gold), moves to the second row of the second column (collecting 2 tons), then to the second row of the third column (collecting 4 tons), and finally to the first row of the fourth column (collecting 5 tons), for a total of 5 + 2 + 4 + 5 = 16 tons of gold collected.

[Naive Approach] Recursive DFS

The idea is to try all possible paths starting from each cell in the first column using recursion.
From each cell (x, y), we recursively call three directions: collectGold(x-1, y+1) -> right upper , collectGold(x, y+1) -> right , and collectGold(x+1, y+1) -> right lower, to explore all valid moves and take the maximum.

C++
#include <iostream>
#include <vector>
using namespace std;

int collectGold(int x, int y, vector<vector<int>> &mat) {
    int n = mat.size(), m = mat[0].size();

    // base case
    if (x < 0 || x >= n || y >= m) {
        return 0;
    }

    // move to the right-upper cell
    int rightUpper = collectGold(x - 1, y + 1, mat);

    // move directly to the right
    int right = collectGold(x, y + 1, mat);

    // move to the right-lower cell
    int rightLower = collectGold(x + 1, y + 1, mat);

    // return the max gold collected from the three options
    return mat[x][y] + max(max(rightUpper, right), rightLower);
}

int maxGold(vector<vector<int>> &mat) {
    int n = mat.size(), m = mat[0].size();
    int result = 0;

    // try starting from each row in the first column
    for (int i = 0; i < n; i++) {
        int gold = collectGold(i, 0, mat);
        result = max(result, gold);
    }

    return result;
}

int main() {
    vector<vector<int>> mat = {
        {1, 3, 1, 5},
        {2, 2, 4, 1},
        {5, 0, 2, 3},
        {0, 6, 1, 2}
    };

    cout << maxGold(mat) << endl;
    return 0;
}
Java
class GfG {

    static int collectGold(int x, int y, int[][] mat) {
        int n = mat.length, m = mat[0].length;

        // base case
        if (x < 0 || x >= n || y >= m) {
            return 0;
        }

        // move to the right-upper cell
        int rightUpper = collectGold(x - 1, y + 1, mat);

        // move directly to the right
        int right = collectGold(x, y + 1, mat);

        // move to the right-lower cell
        int rightLower = collectGold(x + 1, y + 1, mat);

        // return the max gold collected from the three options
        return mat[x][y] + Math.max(Math.max(rightUpper, right), rightLower);
    }

    static int maxGold(int[][] mat) {
        int n = mat.length, m = mat[0].length;
        int result = 0;

        // try starting from each row in the first column
        for (int i = 0; i < n; i++) {
            int gold = collectGold(i, 0, mat);
            result = Math.max(result, gold);
        }

        return result;
    }

    public static void main(String[] args) {
        int[][] mat = {
            {1, 3, 1, 5},
            {2, 2, 4, 1},
            {5, 0, 2, 3},
            {0, 6, 1, 2}
        };

        System.out.println(maxGold(mat));
    }
}
Python
def collectGold(x, y, mat):
    n = len(mat)
    m = len(mat[0])

    # base case
    if x < 0 or x >= n or y >= m:
        return 0

    # move to the right-upper cell
    rightUpper = collectGold(x - 1, y + 1, mat)

    # move directly to the right
    right = collectGold(x, y + 1, mat)

    # move to the right-lower cell
    rightLower = collectGold(x + 1, y + 1, mat)

    # return the max gold collected from the three options
    return mat[x][y] + max(rightUpper, right, rightLower)

def maxGold(mat):
    n = len(mat)
    m = len(mat[0])
    result = 0

    # try starting from each row in the first column
    for i in range(n):
        gold = collectGold(i, 0, mat)
        result = max(result, gold)

    return result

if  __name__ == "__main__":
    mat = [
        [1, 3, 1, 5],
        [2, 2, 4, 1],
        [5, 0, 2, 3],
        [0, 6, 1, 2]
    ]

    print(maxGold(mat))
C#
using System;

class GfG {

    static int collectGold(int x, int y, int[][] mat) {
        int n = mat.Length, m = mat[0].Length;

        // base case
        if (x < 0 || x >= n || y >= m) {
            return 0;
        }

        // move to the right-upper cell
        int rightUpper = collectGold(x - 1, y + 1, mat);

        // move directly to the right
        int right = collectGold(x, y + 1, mat);

        // move to the right-lower cell
        int rightLower = collectGold(x + 1, y + 1, mat);

        // return the max gold collected from the three options
        return mat[x][y] + Math.Max(Math.Max(rightUpper, right), rightLower);
    }

    static int maxGold(int[][] mat) {
        int n = mat.Length, m = mat[0].Length;
        int result = 0;

        // try starting from each row in the first column
        for (int i = 0; i < n; i++) {
            int gold = collectGold(i, 0, mat);
            result = Math.Max(result, gold);
        }

        return result;
    }

    static void Main() {
        int[][] mat = new int[][] {
            new int[] {1, 3, 1, 5},
            new int[] {2, 2, 4, 1},
            new int[] {5, 0, 2, 3},
            new int[] {0, 6, 1, 2}
        };

        Console.WriteLine(maxGold(mat));
    }
}
JavaScript
function collectGold(x, y, mat) {
    let n = mat.length, m = mat[0].length;

    // base case
    if (x < 0 || x >= n || y >= m) {
        return 0;
    }

    // move to the right-upper cell
    let rightUpper = collectGold(x - 1, y + 1, mat);

    // move directly to the right
    let right = collectGold(x, y + 1, mat);

    // move to the right-lower cell
    let rightLower = collectGold(x + 1, y + 1, mat);

    // return the max gold collected from the three options
    return mat[x][y] + Math.max(rightUpper, right, rightLower);
}

function maxGold(mat) {
    let n = mat.length, m = mat[0].length;
    let result = 0;

    // try starting from each row in the first column
    for (let i = 0; i < n; i++) {
        let gold = collectGold(i, 0, mat);
        result = Math.max(result, gold);
    }

    return result;
}

// Driver Code
let mat = [
    [1, 3, 1, 5],
    [2, 2, 4, 1],
    [5, 0, 2, 3],
    [0, 6, 1, 2]
];

console.log(maxGold(mat));

Output
16

Time Complexity: O(3^(n * m)), from each cell, 3 recursive calls are made, leading to exponential growth.
Auxiliary Space: O(n × m) due to recursion stack in the worst case (depth can go up to m steps, each from different rows).

[Better approach 1] Top-Down Dynamic Programming (Memoization) - O(n×m) Time and O(n×m) Space

The idea is to start from each cell in the first column and explore all valid paths using dfs.
At each step (x, y), we try three moves: collectGold(x-1, y+1) -> right upper , collectGold(x, y+1) -> right , and collectGold(x+1, y+1) -> right lower.
We store results in a memo table to avoid recalculating overlapping subproblems.

C++
#include <iostream>
#include <vector>
using namespace std;

int collectGold(int x, int y, vector<vector<int>> &mat,
                                vector<vector<int>> &memo) {
    int n = mat.size(), m = mat[0].size();

    // base case
    if (x < 0 || x >= n || y >= m) {
        return 0;
    }

    // return already computed value
    if (memo[x][y] != -1) {
        return memo[x][y];
    }

    // move to the right-upper cell
    int rightUpper = collectGold(x - 1, y + 1, mat, memo);

    // move directly to the right
    int right = collectGold(x, y + 1, mat, memo);

    // move to the right-lower cell
    int rightLower = collectGold(x + 1, y + 1, mat, memo);

    // store and return the max gold 
    // collected from the three options
    return memo[x][y] = mat[x][y] + 
                        max(max(rightUpper, right), rightLower);
}

int maxGold(vector<vector<int>> &mat) {
    int n = mat.size(), m = mat[0].size();
    int result = 0;

    // initialize memo with -1
    vector<vector<int>> memo(n, vector<int>(m, -1));

    // try starting from each row in the first column
    for (int i = 0; i < n; i++) {
        int gold = collectGold(i, 0, mat, memo);
        result = max(result, gold);
    }

    return result;
}

int main() {
    vector<vector<int>> mat = {
        {1, 3, 1, 5},
        {2, 2, 4, 1},
        {5, 0, 2, 3},
        {0, 6, 1, 2}
    };

    cout << maxGold(mat) << endl;
    return 0;
}
Java
import java.util.Arrays;

class GfG {

    static int collectGold(int x, int y, int[][] mat, int[][] memo) {
        int n = mat.length, m = mat[0].length;

        // base case
        if (x < 0 || x >= n || y >= m) {
            return 0;
        }

        // return already computed value
        if (memo[x][y] != -1) {
            return memo[x][y];
        }

        // move to the right-upper cell
        int rightUpper = collectGold(x - 1, y + 1, mat, memo);

        // move directly to the right
        int right = collectGold(x, y + 1, mat, memo);

        // move to the right-lower cell
        int rightLower = collectGold(x + 1, y + 1, mat, memo);

        // store and return the max gold 
        // collected from the three options
        return memo[x][y] = mat[x][y] + 
                        Math.max(Math.max(rightUpper, right), rightLower);
    }

    static int maxGold(int[][] mat) {
        int n = mat.length, m = mat[0].length;
        int result = 0;

        // initialize memo with -1
        int[][] memo = new int[n][m];
        for (int[] row : memo) {
            Arrays.fill(row, -1);
        }

        // try starting from each row in the first column
        for (int i = 0; i < n; i++) {
            int gold = collectGold(i, 0, mat, memo);
            result = Math.max(result, gold);
        }

        return result;
    }

    public static void main(String[] args) {
        int[][] mat = {
            {1, 3, 1, 5},
            {2, 2, 4, 1},
            {5, 0, 2, 3},
            {0, 6, 1, 2}
        };

        System.out.println(maxGold(mat));
    }
}
Python
def collectGold(x, y, mat, memo):
    n = len(mat)
    m = len(mat[0])

    # base case
    if x < 0 or x >= n or y >= m:
        return 0

    # return already computed value
    if memo[x][y] != -1:
        return memo[x][y]

    # move to the right-upper cell
    rightUpper = collectGold(x - 1, y + 1, mat, memo)

    # move directly to the right
    right = collectGold(x, y + 1, mat, memo)

    # move to the right-lower cell
    rightLower = collectGold(x + 1, y + 1, mat, memo)

    # store and return the max gold 
    # collected from the three options
    memo[x][y] = mat[x][y] + max(rightUpper, right, rightLower)
    return memo[x][y]

def maxGold(mat):
    n = len(mat)
    m = len(mat[0])
    result = 0

    # initialize memo with -1
    memo = [[-1 for _ in range(m)] for _ in range(n)]

    # try starting from each row in the first column
    for i in range(n):
        gold = collectGold(i, 0, mat, memo)
        result = max(result, gold)

    return result


if __name__ == "__main__":
    
    mat = [
        [1, 3, 1, 5],
        [2, 2, 4, 1],
        [5, 0, 2, 3],
        [0, 6, 1, 2]
    ]
    print(maxGold(mat))
C#
using System;

class GfG {

    static int collectGold(int x, int y, int[][] mat, int[][] memo) {
        int n = mat.Length, m = mat[0].Length;

        // base case
        if (x < 0 || x >= n || y >= m) {
            return 0;
        }

        // return already computed value
        if (memo[x][y] != -1) {
            return memo[x][y];
        }

        // move to the right-upper cell
        int rightUpper = collectGold(x - 1, y + 1, mat, memo);

        // move directly to the right
        int right = collectGold(x, y + 1, mat, memo);

        // move to the right-lower cell
        int rightLower = collectGold(x + 1, y + 1, mat, memo);

        // store and return the max gold collected from the three options
        return memo[x][y] = mat[x][y] + 
                Math.Max(Math.Max(rightUpper, right), rightLower);
    }

    static int maxGold(int[][] mat) {
        int n = mat.Length, m = mat[0].Length;
        int result = 0;

        // initialize memo with -1
        int[][] memo = new int[n][];
        for (int i = 0; i < n; i++) {
            memo[i] = new int[m];
            for (int j = 0; j < m; j++) {
                memo[i][j] = -1;
            }
        }

        // try starting from each row in the first column
        for (int i = 0; i < n; i++) {
            int gold = collectGold(i, 0, mat, memo);
            result = Math.Max(result, gold);
        }

        return result;
    }

    static void Main() {
        int[][] mat = new int[][] {
            new int[] {1, 3, 1, 5},
            new int[] {2, 2, 4, 1},
            new int[] {5, 0, 2, 3},
            new int[] {0, 6, 1, 2}
        };

        Console.WriteLine(maxGold(mat));
    }
}
JavaScript
function collectGold(x, y, mat, memo) {
    const n = mat.length, m = mat[0].length;

    // base case
    if (x < 0 || x >= n || y >= m) {
        return 0;
    }

    // return already computed value
    if (memo[x][y] !== -1) {
        return memo[x][y];
    }

    // move to the right-upper cell
    const rightUpper = collectGold(x - 1, y + 1, mat, memo);

    // move directly to the right
    const right = collectGold(x, y + 1, mat, memo);

    // move to the right-lower cell
    const rightLower = collectGold(x + 1, y + 1, mat, memo);

    // store and return the max gold collected 
    // from the three options
    memo[x][y] = mat[x][y] + Math.max(rightUpper, 
                                    right, rightLower);
    return memo[x][y];
}

function maxGold(mat) {
    const n = mat.length, m = mat[0].length;
    let result = 0;

    // initialize memo with -1
    const memo = 
        Array.from({ length: n }, () => Array(m).fill(-1));

    // try starting from each row in the first column
    for (let i = 0; i < n; i++) {
        const gold = collectGold(i, 0, mat, memo);
        result = Math.max(result, gold);
    }

    return result;
}

// Driver Code
const mat = [
    [1, 3, 1, 5],
    [2, 2, 4, 1],
    [5, 0, 2, 3],
    [0, 6, 1, 2]
];

console.log(maxGold(mat));

Output
16

[Better approach 2] Bottom-Up Dynamic Programming (Tabulation) - O(n×m) Space and O(n×m) Space

We define dp[x][y] as the maximum gold that can be collected starting from cell (x, y).
At each cell, we consider three possible moves: right upper (x-1, y+1), right (x, y+1), and right lower (x+1, y+1).
So the relation becomes: dp[x][y] = mat[x][y] + max(dp[x-1][y+1], dp[x][y+1], dp[x+1][y+1]), ensuring all indices are within bounds.

C++
#include <iostream>
#include <vector>
using namespace std;

int maxGold(vector<vector<int>> &mat) {
    int n = mat.size(), m = mat[0].size();

    // create a dp table with same dimensions
    vector<vector<int>> dp(n, vector<int>(m, 0));

    // fill the last column with initial gold values
    for (int i = 0; i < n; i++) {
        dp[i][m - 1] = mat[i][m - 1];
    }

    // fill the dp table from second-last column to first
    for (int y = m - 2; y >= 0; y--) {
        for (int x = 0; x < n; x++) {

            // move to the right-upper cell
            int rightUpper = (x > 0) ? dp[x - 1][y + 1] : 0;

            // move directly to the right
            int right = dp[x][y + 1];

            // move to the right-lower cell
            int rightLower = (x < n - 1) ? dp[x + 1][y + 1] : 0;

            // store the max gold from the three options
            dp[x][y] = mat[x][y] + 
                    max(max(rightUpper, right), rightLower);
        }
    }

    // find the maximum in the first column
    int result = 0;
    for (int i = 0; i < n; i++) {
        result = max(result, dp[i][0]);
    }

    return result;
}

int main() {
    
    vector<vector<int>> mat = {
        {1, 3, 1, 5},
        {2, 2, 4, 1},
        {5, 0, 2, 3},
        {0, 6, 1, 2}
    };

    cout << maxGold(mat) << endl;
    return 0;
}
Java
class GfG {

    static int maxGold(int[][] mat) {
        int n = mat.length, m = mat[0].length;

        // create a dp table with same dimensions
        int[][] dp = new int[n][m];

        // fill the last column with initial gold values
        for (int i = 0; i < n; i++) {
            dp[i][m - 1] = mat[i][m - 1];
        }

        // fill the dp table from second-last column to first
        for (int y = m - 2; y >= 0; y--) {
            for (int x = 0; x < n; x++) {

                // move to the right-upper cell
                int rightUpper = (x > 0) ? dp[x - 1][y + 1] : 0;

                // move directly to the right
                int right = dp[x][y + 1];

                // move to the right-lower cell
                int rightLower = (x < n - 1) ? dp[x + 1][y + 1] : 0;

                // store the max gold from the three options
                dp[x][y] = mat[x][y] + Math.max(
                              Math.max(rightUpper, right), rightLower);
            }
        }

        // find the maximum in the first column
        int result = 0;
        for (int i = 0; i < n; i++) {
            result = Math.max(result, dp[i][0]);
        }

        return result;
    }

    public static void main(String[] args) {
        int[][] mat = {
            {1, 3, 1, 5},
            {2, 2, 4, 1},
            {5, 0, 2, 3},
            {0, 6, 1, 2}
        };

        System.out.println(maxGold(mat));
    }
}
Python
def maxGold(mat):
    n = len(mat)
    m = len(mat[0])

    # create a dp table with same dimensions
    dp = [[0 for _ in range(m)] for _ in range(n)]

    # fill the last column with initial gold values
    for i in range(n):
        dp[i][m - 1] = mat[i][m - 1]

    # fill the dp table from second-last column to first
    for y in range(m - 2, -1, -1):
        for x in range(n):

            # move to the right-upper cell
            rightUpper = dp[x - 1][y + 1] if x > 0 else 0

            # move directly to the right
            right = dp[x][y + 1]

            # move to the right-lower cell
            rightLower = dp[x + 1][y + 1] if x < n - 1 else 0

            # store the max gold from the three options
            dp[x][y] = mat[x][y] + max(rightUpper, right, rightLower)

    # find the maximum in the first column
    result = 0
    for i in range(n):
        result = max(result, dp[i][0])

    return result

def main():
    mat = [
        [1, 3, 1, 5],
        [2, 2, 4, 1],
        [5, 0, 2, 3],
        [0, 6, 1, 2]
    ]
    print(maxGold(mat))

main()
C#
using System;

class GfG {

    static int maxGold(int[][] mat) {
        int n = mat.Length, m = mat[0].Length;

        // create a dp table with same dimensions
        int[][] dp = new int[n][];
        for (int i = 0; i < n; i++) {
            dp[i] = new int[m];
        }

        // fill the last column with initial gold values
        for (int i = 0; i < n; i++) {
            dp[i][m - 1] = mat[i][m - 1];
        }

        // fill the dp table from second-last column to first
        for (int y = m - 2; y >= 0; y--) {
            for (int x = 0; x < n; x++) {

                // move to the right-upper cell
                int rightUpper = (x > 0) ? dp[x - 1][y + 1] : 0;

                // move directly to the right
                int right = dp[x][y + 1];

                // move to the right-lower cell
                int rightLower = (x < n - 1) ? dp[x + 1][y + 1] : 0;

                // store the max gold from the three options
                dp[x][y] = mat[x][y] + 
                           Math.Max(Math.Max(rightUpper, right), rightLower);
            }
        }

        // find the maximum in the first column
        int result = 0;
        for (int i = 0; i < n; i++) {
            result = Math.Max(result, dp[i][0]);
        }

        return result;
    }

    static void Main() {
        int[][] mat = new int[][] {
            new int[] {1, 3, 1, 5},
            new int[] {2, 2, 4, 1},
            new int[] {5, 0, 2, 3},
            new int[] {0, 6, 1, 2}
        };

        Console.WriteLine(maxGold(mat));
    }
}
JavaScript
function maxGold(mat) {
    const n = mat.length, m = mat[0].length;

    // create a dp table with same dimensions
    const dp = Array.from({ length: n }, () => Array(m).fill(0));

    // fill the last column with initial gold values
    for (let i = 0; i < n; i++) {
        dp[i][m - 1] = mat[i][m - 1];
    }

    // fill the dp table from second-last column to first
    for (let y = m - 2; y >= 0; y--) {
        for (let x = 0; x < n; x++) {

            // move to the right-upper cell
            let rightUpper = x > 0 ? dp[x - 1][y + 1] : 0;

            // move directly to the right
            let right = dp[x][y + 1];

            // move to the right-lower cell
            let rightLower = x < n - 1 ? dp[x + 1][y + 1] : 0;

            // store the max gold from the three options
            dp[x][y] = mat[x][y] + 
                       Math.max(rightUpper, right, rightLower);
        }
    }

    // find the maximum in the first column
    let result = 0;
    for (let i = 0; i < n; i++) {
        result = Math.max(result, dp[i][0]);
    }

    return result;
}

// Driver Code
const mat = [
    [1, 3, 1, 5],
    [2, 2, 4, 1],
    [5, 0, 2, 3],
    [0, 6, 1, 2]
];

console.log(maxGold(mat));

Output
16

[Efficient approach] Space-Optimized Tabulation – O(n×m) Time and O(n) Space

Instead of storing the entire dp[n][m] table, we only track gold values for the current and next columns using two 1D arrays: prev and curr.
We iterate from right to left, updating curr[x] using prev[x-1] -> right-upper, prev[x] -> right, and prev[x+1] -> right-lower, then swap prev and curr for the next round.
The state is given by: curr[x] = mat[x][y] + max(prev[x-1], prev[x], prev[x+1]), ensuring all indices are within bounds.

C++
#include <iostream>
#include <vector>
using namespace std;

int maxGold(vector<vector<int>> &mat) {
    int n = mat.size(), m = mat[0].size();

    // initialize prev with the last column of the matrix
    vector<int> prev(n, 0);
    for (int i = 0; i < n; i++) {
        prev[i] = mat[i][m - 1];
    }

    // move from second-last column to the first
    for (int y = m - 2; y >= 0; y--) {
        vector<int> curr(n, 0);

        for (int x = 0; x < n; x++) {

            // move to the right-upper cell
            int rightUpper = (x > 0) ? prev[x - 1] : 0;

            // move directly to the right
            int right = prev[x];

            // move to the right-lower cell
            int rightLower = (x < n - 1) ? prev[x + 1] : 0;

            // store the max gold from the three options
            curr[x] = mat[x][y] + 
                    max(max(rightUpper, right), rightLower);
        }

        // update prev to current for the next iteration
        prev = curr;
    }

    // find the maximum in the final prev array
    int result = 0;
    for (int i = 0; i < n; i++) {
        result = max(result, prev[i]);
    }

    return result;
}

int main() {
    vector<vector<int>> mat = {
        {1, 3, 1, 5},
        {2, 2, 4, 1},
        {5, 0, 2, 3},
        {0, 6, 1, 2}
    };

    cout << maxGold(mat) << endl;
    return 0;
}
Java
class GfG {

    static int maxGold(int[][] mat) {
        int n = mat.length, m = mat[0].length;

        // initialize prev with the last column of the matrix
        int[] prev = new int[n];
        for (int i = 0; i < n; i++) {
            prev[i] = mat[i][m - 1];
        }

        // move from second-last column to the first
        for (int y = m - 2; y >= 0; y--) {
            int[] curr = new int[n];

            for (int x = 0; x < n; x++) {

                // move to the right-upper cell
                int rightUpper = (x > 0) ? prev[x - 1] : 0;

                // move directly to the right
                int right = prev[x];

                // move to the right-lower cell
                int rightLower = (x < n - 1) ? prev[x + 1] : 0;

                // store the max gold from the three options
                curr[x] = mat[x][y] + 
                        Math.max(Math.max(rightUpper, right), rightLower);
            }

            // update prev to current for the next iteration
            prev = curr;
        }

        // find the maximum in the final prev array
        int result = 0;
        for (int i = 0; i < n; i++) {
            result = Math.max(result, prev[i]);
        }

        return result;
    }

    public static void main(String[] args) {
        int[][] mat = {
            {1, 3, 1, 5},
            {2, 2, 4, 1},
            {5, 0, 2, 3},
            {0, 6, 1, 2}
        };

        System.out.println(maxGold(mat));
    }
}
Python
def maxGold(mat):
    n = len(mat)
    m = len(mat[0])

    # initialize prev with the last column of the matrix
    prev = [mat[i][m - 1] for i in range(n)]

    # move from second-last column to the first
    for y in range(m - 2, -1, -1):
        curr = [0] * n

        for x in range(n):

            # move to the right-upper cell
            rightUpper = prev[x - 1] if x > 0 else 0

            # move directly to the right
            right = prev[x]

            # move to the right-lower cell
            rightLower = prev[x + 1] if x < n - 1 else 0

            # store the max gold from the three options
            curr[x] = mat[x][y] + max(rightUpper, right, rightLower)

        # update prev to current for the next iteration
        prev = curr

    # find the maximum in the final prev array
    result = max(prev)
    return result

def main():
    mat = [
        [1, 3, 1, 5],
        [2, 2, 4, 1],
        [5, 0, 2, 3],
        [0, 6, 1, 2]
    ]
    print(maxGold(mat))

main()
C#
using System;

class GfG {

    static int maxGold(int[][] mat) {
        int n = mat.Length, m = mat[0].Length;

        // initialize prev with the last column of the matrix
        int[] prev = new int[n];
        for (int i = 0; i < n; i++) {
            prev[i] = mat[i][m - 1];
        }

        // move from second-last column to the first
        for (int y = m - 2; y >= 0; y--) {
            int[] curr = new int[n];

            for (int x = 0; x < n; x++) {

                // move to the right-upper cell
                int rightUpper = (x > 0) ? prev[x - 1] : 0;

                // move directly to the right
                int right = prev[x];

                // move to the right-lower cell
                int rightLower = (x < n - 1) ? prev[x + 1] : 0;

                // store the max gold from the three options
                curr[x] = mat[x][y] + 
                    Math.Max(Math.Max(rightUpper, right), rightLower);
            }

            // update prev to current for the next iteration
            prev = curr;
        }

        // find the maximum in the final prev array
        int result = 0;
        for (int i = 0; i < n; i++) {
            result = Math.Max(result, prev[i]);
        }

        return result;
    }

    static void Main() {
        int[][] mat = new int[][] {
            new int[] {1, 3, 1, 5},
            new int[] {2, 2, 4, 1},
            new int[] {5, 0, 2, 3},
            new int[] {0, 6, 1, 2}
        };

        Console.WriteLine(maxGold(mat));
    }
}
JavaScript
function maxGold(mat) {
    const n = mat.length, m = mat[0].length;

    // initialize prev with the last column of the matrix
    let prev = new Array(n);
    for (let i = 0; i < n; i++) {
        prev[i] = mat[i][m - 1];
    }

    // move from second-last column to the first
    for (let y = m - 2; y >= 0; y--) {
        let curr = new Array(n).fill(0);

        for (let x = 0; x < n; x++) {

            // move to the right-upper cell
            let rightUpper = (x > 0) ? prev[x - 1] : 0;

            // move directly to the right
            let right = prev[x];

            // move to the right-lower cell
            let rightLower = (x < n - 1) ? prev[x + 1] : 0;

            // store the max gold from the three options
            curr[x] = mat[x][y] + 
                    Math.max(rightUpper, right, rightLower);
        }

        // update prev to current for the next iteration
        prev = curr;
    }

    // find the maximum in the final prev array
    let result = Math.max(...prev);
    return result;
}

// Driver Code
const mat = [
    [1, 3, 1, 5],
    [2, 2, 4, 1],
    [5, 0, 2, 3],
    [0, 6, 1, 2]
];

console.log(maxGold(mat));

Output
16

[Expected Approach] In-place Dynamic Programming from Right to Left - O(n×m) Time ans O(1) Space

The idea is to use in-place tabulation, traversing the matrix from right to left. For each cell mat[x][y], we calculate the maximum gold that can be collected if we come from one of the three cells in the next (right) column: mat[x-1][y+1] → right-upper, mat[x][y+1] → right, mat[x+1][y+1] → right-lower.
We update the current cell as: mat[x][y] = mat[x][y] + max(mat[x-1][y+1], mat[x][y+1], mat[x+1][y+1]).
This update is safe because we are moving right to left, so any update to mat[x][y] does not affect future calculations — the values to the right (which we depend on) have already been processed and won’t be modified again.

C++
#include <iostream>
#include <vector>
#include <climits>
using namespace std;

bool isValid(int x, int y, int n, int m) {
    return x >= 0 && x < n && y >= 0 && y < m;
}

int maxGold(vector<vector<int>> &mat) {
    
    int n = mat.size(), m = mat[0].size();

    for (int y = m - 2; y >= 0; y--) {
        for (int x = 0; x < n; x++) {
            int maxprev = 0;

            // move from right-upper cell
            if (isValid(x - 1, y + 1, n, m)) {
                maxprev = max(maxprev, mat[x - 1][y + 1]);
            }

            // move from right cell
            if (isValid(x, y + 1, n, m)) {
                maxprev = max(maxprev, mat[x][y + 1]);
            }

            // move from right-lower cell
            if (isValid(x + 1, y + 1, n, m)) {
                maxprev = max(maxprev, mat[x + 1][y + 1]);
            }

            // store the max gold from the three options
            mat[x][y] += maxprev;
        }
    }

    // find the maximum in the first column
    int result = 0;
    for (int i = 0; i < n; i++) {
        result = max(result, mat[i][0]);
    }

    return result;
}

int main() {
    vector<vector<int>> mat = {
        {1, 3, 1, 5},
        {2, 2, 4, 1},
        {5, 0, 2, 3},
        {0, 6, 1, 2}
    };

    cout << maxGold(mat);
    return 0;
}
Java
class GfG {

    static boolean isValid(int x, int y, int n, int m) {
        return x >= 0 && x < n && y >= 0 && y < m;
    }

    static int maxGold(int[][] mat) {
        int n = mat.length, m = mat[0].length;

        for (int y = m - 2; y >= 0; y--) {
            for (int x = 0; x < n; x++) {
                int maxprev = 0;

                // move from right-upper cell
                if (isValid(x - 1, y + 1, n, m)) {
                    maxprev = Math.max(maxprev, mat[x - 1][y + 1]);
                }

                // move from right cell
                if (isValid(x, y + 1, n, m)) {
                    maxprev = Math.max(maxprev, mat[x][y + 1]);
                }

                // move from right-lower cell
                if (isValid(x + 1, y + 1, n, m)) {
                    maxprev = Math.max(maxprev, mat[x + 1][y + 1]);
                }

                // store the max gold from the three options
                mat[x][y] += maxprev;
            }
        }

        // find the maximum in the first column
        int result = 0;
        for (int i = 0; i < n; i++) {
            result = Math.max(result, mat[i][0]);
        }

        return result;
    }

    public static void main(String[] args) {
        int[][] mat = {
            {1, 3, 1, 5},
            {2, 2, 4, 1},
            {5, 0, 2, 3},
            {0, 6, 1, 2}
        };

        System.out.println(maxGold(mat));
    }
}
Python
def isValid(x, y, n, m):
    return 0 <= x < n and 0 <= y < m

def maxGold(mat):
    n = len(mat)
    m = len(mat[0])

    for y in range(m - 2, -1, -1):
        for x in range(n):
            maxprev = 0

            # move from right-upper cell
            if isValid(x - 1, y + 1, n, m):
                maxprev = max(maxprev, mat[x - 1][y + 1])

            # move from right cell
            if isValid(x, y + 1, n, m):
                maxprev = max(maxprev, mat[x][y + 1])

            # move from right-lower cell
            if isValid(x + 1, y + 1, n, m):
                maxprev = max(maxprev, mat[x + 1][y + 1])

            # store the max gold from the three options
            mat[x][y] += maxprev

    # find the maximum in the first column
    result = max(mat[i][0] for i in range(n))
    return result

if __name__ == "__main__":
    mat = [
        [1, 3, 1, 5],
        [2, 2, 4, 1],
        [5, 0, 2, 3],
        [0, 6, 1, 2]
    ]
    print(maxGold(mat))
C#
using System;

class GfG {

    static bool isValid(int x, int y, int n, int m) {
        return x >= 0 && x < n && y >= 0 && y < m;
    }

    static int maxGold(int[][] mat) {
        int n = mat.Length, m = mat[0].Length;

        for (int y = m - 2; y >= 0; y--) {
            for (int x = 0; x < n; x++) {
                int maxprev = 0;

                // move from right-upper cell
                if (isValid(x - 1, y + 1, n, m)) {
                    maxprev = Math.Max(maxprev, mat[x - 1][y + 1]);
                }

                // move from right cell
                if (isValid(x, y + 1, n, m)) {
                    maxprev = Math.Max(maxprev, mat[x][y + 1]);
                }

                // move from right-lower cell
                if (isValid(x + 1, y + 1, n, m)) {
                    maxprev = Math.Max(maxprev, mat[x + 1][y + 1]);
                }

                // store the max gold from the three options
                mat[x][y] += maxprev;
            }
        }

        // find the maximum in the first column
        int result = 0;
        for (int i = 0; i < n; i++) {
            result = Math.Max(result, mat[i][0]);
        }

        return result;
    }

    static void Main() {
        int[][] mat = new int[][] {
            new int[] {1, 3, 1, 5},
            new int[] {2, 2, 4, 1},
            new int[] {5, 0, 2, 3},
            new int[] {0, 6, 1, 2}
        };

        Console.WriteLine(maxGold(mat));
    }
}
JavaScript
function isValid(x, y, n, m) {
    return x >= 0 && x < n && y >= 0 && y < m;
}

function maxGold(mat) {
    const n = mat.length, m = mat[0].length;

    for (let y = m - 2; y >= 0; y--) {
        for (let x = 0; x < n; x++) {
            let maxprev = 0;

            // move from right-upper cell
            if (isValid(x - 1, y + 1, n, m)) {
                maxprev = Math.max(maxprev, mat[x - 1][y + 1]);
            }

            // move from right cell
            if (isValid(x, y + 1, n, m)) {
                maxprev = Math.max(maxprev, mat[x][y + 1]);
            }

            // move from right-lower cell
            if (isValid(x + 1, y + 1, n, m)) {
                maxprev = Math.max(maxprev, mat[x + 1][y + 1]);
            }

            // store the max gold from the three options
            mat[x][y] += maxprev;
        }
    }

    // find the maximum in the first column
    let result = 0;
    for (let i = 0; i < n; i++) {
        result = Math.max(result, mat[i][0]);
    }

    return result;
}

// Driver Code
const mat = [
    [1, 3, 1, 5],
    [2, 2, 4, 1],
    [5, 0, 2, 3],
    [0, 6, 1, 2]
];

console.log(maxGold(mat));

Output
16

Gold Mine Problem | DSA Problem
Article Tags :

Explore