0

For example I have 2d matrix like this:

.X..X..
2...2..
..X.1..
2.....X

Starting at (0,0),I can move down 1 cell or right 1 cell at a time, cell 'X' is an obstacle. Find the path with maximum sum. The answer for the above input is: DRRRRRD (D for down, R for right) I could find the sum using dfs and a DP array but I don't know how can I trace the optimal path with this approach.

public static int dfs(char[][] matrix, int i, int j, int[][] cache) {
    if (cache[i][j] != 0) {
        return cache[i][j];
    }

    if (matrix[i][j] != 'X' && matrix[i][j] != 'x' && matrix[i][j] != '.') {
        cache[i][j] += Character.getNumericValue(matrix[i][j]);

    }
    
    int iDown = i + 1;
    int jRight = j + 1;
    int dirDown = cache[i][j];
    int dirRight = cache[i][j];

    if (iDown < matrix.length && matrix[iDown][j] != 'X' && matrix[iDown][j] != 'x') {
        dirDown += dfs(matrix, iDown, j, cache);
    }

    if (jRight < matrix[0].length && matrix[i][jRight] != 'X' && matrix[i][jRight] != 'x') {
        dirRight += dfs(matrix, i, jRight, cache);
    }

    cache[i][j] = Math.max(dirDown, dirRight);

    return cache[i][j];
}
Zoe
  • 27,060
  • 21
  • 118
  • 148
nanh
  • 13
  • 3

1 Answers1

0

You can modify dfs to keep track of the path and have it return a pair of Integer (the sum) and a String representing the path:

import java.util.Map;
import java.util.Map.Entry;

class Main   {
    public static void main(String[] args) {

        char[][] matrix = {
                {'.','X','.','.','X','.','.'},
                {'2','.','.','.','2','.','.'},
                {'.','.','X','.','1','.','.'},
                {'2','.','.','.','.','.','X'}
        };
        Entry<Integer, String> result = dfs(matrix,0,0,new int[matrix.length][matrix[0].length],"");
        System.out.println(result.getKey() +" "+ result.getValue());
    }

    //Entry is used as a container for an int-string pair
    public static Entry<Integer, String> dfs(char[][] matrix, int i, int j, int[][] cache, String path) {

        cache[i][j]=0;//clear previous sum 

        if (matrix[i][j] != 'X' && matrix[i][j] != 'x' && matrix[i][j] != '.') {
            cache[i][j] += Character.getNumericValue(matrix[i][j]);
        }

        int iDown = i + 1;
        int jRight = j + 1;
        Entry<Integer,String> resultDown = null;
        Entry<Integer,String> resultRight = null;

        if (iDown < matrix.length && matrix[iDown][j] != 'X' && matrix[iDown][j] != 'x') {
            resultDown =  dfs(matrix, iDown, j, cache, path+"D");
            if(resultDown.getKey() <= 0) {  //no values found
                resultDown = null;
            }
        }

        if (jRight < matrix[0].length && matrix[i][jRight] != 'X' && matrix[i][jRight] != 'x') {
            resultRight =  dfs(matrix, i, jRight, cache, path+"R");
            if(resultRight.getKey() <= 0) { //no values found
                resultRight = null;
            }
        }

        //no values found moving right or down
        if(resultDown == null && resultRight == null) return Map.entry(cache[i][j], path);

        String newPath = path;

        if(resultDown != null && resultRight != null){ //values found in both directions
            if(resultDown.getKey() > resultRight.getKey()) {
                cache[i][j]+= resultDown.getKey();
                newPath = resultDown.getValue();
            }else {
                cache[i][j] += resultRight.getKey();
                newPath = resultRight.getValue();
            }
        }else /*values found only in one direction*/if(resultDown != null ) {
            cache[i][j] += resultDown.getKey();
            newPath = resultDown.getValue();
        }else{
            cache[i][j] += resultRight.getKey();
            newPath = resultRight.getValue();
        }

        return  Map.entry(cache[i][j] , newPath);
    }
}

A better and more Object Oriented approach is to define a Node object, for example:

    class Node {

    private final char value;
    private String direction;
    private Node child = null;
    private int sum = 0;

    public Node(char value) {
        this.value = value;
    }

    public String getDirection() {
        return direction;
    }

    public void setDirection(String direction) {
        this.direction = direction;
    }

    public Node getChild() {
        return child;
    }

    public void setChild(Node parent) {
        child = parent;
    }

    public char getValue() {
        return value;
    }

    public int getSum() {
        return sum;
    }

    public void addToSum(int add) {
        sum += add;
    }
}

and run dfs on a graph of Nodes (for example Node[][]).

c0der
  • 18,467
  • 6
  • 33
  • 65
  • I think your solution fails this test, it supposes to be 18, your code provides 12 .x..x.........x........ ......2................ .................6..... 2...........3....1..... .X4........X.X...1..... .......2.......X.2..... 2.2........X4..1....... ....................... ...X..3.........2...... 1..X......2......3..X.. 2XXX...........X.....X. – nanh Nov 28 '21 at 10:06
  • Maybe so. I'll leave the debugging to you. This is a POC, to show you a possible direction. It is not meant to be a fully debugged version. Also [edit] your post and hard code any test data and its expected output. – c0der Nov 28 '21 at 11:30
  • posted an improved version – c0der Nov 29 '21 at 05:24