如何在矩阵中找到最短路径

时间:2016-07-14 14:32:19

标签: java recursion matrix shortest-path

我在JAVA中有一个问题,无论我多久尝试考虑解决方案,我都无法解决: 有一个矩阵,我需要找到从Mat [0] [0]到矩阵右下角的最短路径,如果其中的数字我只能进入相邻的正方形(没有对角线)比我现在的那个还要大。

For example:
    0   1   2   3   4
0 { 5   13  2   5   2 
1   58  24  32  3   24 
2   2   7   33  1   7 
3   45  40  37  24  70
4   47  34  12  25  2 
5   52  56  68  76  100}

所以一个有效的解决方案是: (0,0) - >(0,1) - >(1,1) - >(2,1) - >(2,2) - >(2,3) - >(3 ,1) - >(3,0) - >(0,4) - >(0,5) - >(5,1) - >(5,2) - >(5,3 ) - >(5,4)

该方法将返回14,因为这是最短路径。

我必须只使用递归方法(没有循环)。

这是我到目前为止所提出的,但我不知道如何找出哪个是最短的。

Public static int shortestPath(int[][]mat)
{
    int length=0;
    int i=0;
    int j=0;
    shortestPath(mat, length, i, j);
}


Private static int shortestPath(int[][]math, int length, int i, int j)
{
    if((i==mat.length)||(j==mat[i].length))
        return length;
    if(shortestPath(mat, length, i+1, j) > shortestPath(mat, length, i, j))
        return length +1;
    if(shortestPath(mat, length, i, j+1) > shortestPath(mat, length, i, j))
        return length +1;
    if shortestPath(mat, length, i-1, j) > shortestPath(mat, length, i, j))
        return length +1;
    if shortestPath(mat, length, i, j-1) > shortestPath(mat, length, i, j))
        return length +1;
}

我不确定这是否是这样做的方式,如果是:我怎么知道哪种方式最短,因为现在它会返回所有可能的方式并将它们添加(我想)。 另外,我想我应该添加一些关于到达矩阵右下角的内容。

代码不应该太复杂。

7 个答案:

答案 0 :(得分:1)

我不确定进入下一个最小值的方法是否最短,但无论如何:

public class Pathfinder {

    private int[][] matrix;
    private int matrixLenghtI;
    private int matrixLenghtJ;

    public Pathfinder(int[][] matrix, int matrixLenghtI, int matrixLenghtJ) {
        this.matrix = matrix;
        this.matrixLenghtI = matrixLenghtI;
        this.matrixLenghtJ = matrixLenghtJ;
    }

    public static void main(String[] args) {

        int matrixLenghtI = 6;
        int matrixLenghtJ = 5;

        int[][] matrix1 = { { 3, 13, 15, 28, 30 }, { 40, 51, 52, 29, 30 }, { 28, 10, 53, 54, 54 },
                { 53, 12, 55, 53, 60 }, { 70, 62, 56, 20, 80 }, { 80, 81, 90, 95, 100 } };

        int[][] matrix2 = { { 5, 13, 2, 5, 2 }, { 58, 24, 32, 3, 24 }, { 2, 7, 33, 1, 7 }, { 45, 40, 37, 24, 70 },
                { 47, 34, 12, 25, 2 }, { 52, 56, 68, 76, 100 } };

        Pathfinder finder1 = new Pathfinder(matrix1, matrixLenghtI, matrixLenghtJ);
        finder1.run();

        Pathfinder finder2 = new Pathfinder(matrix2, matrixLenghtI, matrixLenghtJ);
        finder2.run();
    }

    private void run() {
        int i = 0;
        int j = 0;

        System.out.print("(" + i + "," + j + ")");
        System.out.println("\nLength: " + find(i, j));
    }

    private int find(int i, int j) {
        int value = matrix[i][j];
        int[] next = { i, j };

        int smallestNeighbour = 101;
        if (i > 0 && matrix[i - 1][j] > value) {
            smallestNeighbour = matrix[i - 1][j];
            next[0] = i - 1;
            next[1] = j;
        }
        if (j > 0 && matrix[i][j - 1] < smallestNeighbour && matrix[i][j - 1] > value) {
            smallestNeighbour = matrix[i][j - 1];
            next[0] = i;
            next[1] = j - 1;
        }
        if (i < matrixLenghtI - 1 && matrix[i + 1][j] < smallestNeighbour && matrix[i + 1][j] > value) {
            smallestNeighbour = matrix[i + 1][j];
            next[0] = i + 1;
            next[1] = j;
        }
        if (j < matrixLenghtJ - 1 && matrix[i][j + 1] < smallestNeighbour && matrix[i][j + 1] > value) {
            smallestNeighbour = matrix[i][j + 1];
            next[0] = i;
            next[1] = j + 1;
        }

        System.out.print("->(" + next[0] + "," + next[1] + ")");

        if (i == matrixLenghtI - 1 && j == matrixLenghtJ - 1)
            return 1;

        return find(next[0], next[1]) + 1;
    }
}

输出:

(0,0)->(0,1)->(0,2)->(0,3)->(1,3)->(1,4)->(2,4)->(3,4)->(4,4)->(5,4)->(5,4)
Length: 10
(0,0)->(0,1)->(1,1)->(1,2)->(2,2)->(3,2)->(3,1)->(3,0)->(4,0)->(5,0)->(5,1)->(5,2)->(5,3)->(5,4)->(5,4)
Length: 14

答案 1 :(得分:1)

我真的很喜欢这个问题。不幸的是我多年没有在Java工作,所以这个答案是伪Java,你必须修复一些语法。可能一些函数参数应该是引用而不是副本;你会搞清楚的(更新:我在下面的python中添加了一个TESTED版本)。

// just a little thing to hold a set of coordinates
class Position 
{
    // not bothering with private / getters
    public int x ;
    public int y ;
    public constructor (int x, int y) 
    {
        this.x = x ;
        this.y = y ;
    }
}

class PathFinder
{
    public void main (void)
    {
        // create a path with just the start position
        start = new Position(0, 0) ;
        path = new Vector() ;
        path.add(start) ;
        // create an empty path to contain the final shortest path
        finalPath = new Vector() ;
        findPath(path, finalPath) ;
        print ("Shortest Path: ") ;
        showPath (finalPath) ;
    }

    private void showPath (Vector path) {
        // print out each position in the path
        iter = path.iterator() ;
        while (pos = iter.next()) {
            print ("(%, %) ", pos.x, pos.y);
        }
        // print out the length of the path
        print ("  Length: %\n", path.size()) ;
    }

    // recursive function to find shortest path
    private void findPath (Vector path, Vector finalPath)
    {
        // always display the current path (it should never be the same path twice)
        showPath(path) ;

        // where are we now?
        here = path.lastElement() ;

        // does the current path find the exit (position 4,5)?
        if (here.x == 4 && here.y == 5) {
            if (finalPath.size() == 0) {
                //finalPath is empty, put the current path in finalPath
                finalPath = path ;
            } else {
                // some other path found the exit already.  Which path is shorter?
                if (finalPath.size() > path.size()) {
                    finalPath = path ;
                }
            }
            // either way, we're at the exit and this path goes no further
            return ;
        }

        // path is not at exit; grope in all directions
        // note the code duplication in this section is unavoidable
        // because it may be necessary to start new paths in three
        // directions from any given position
        // If no new paths are available from the current position,
        // no new calls to findPath() will happen and 
        // the recursion will collapse.

        if (here.x > 0 && matrix[here.x-1][here.y] > matrix[here.x][here.y]) {
            // we can move left
            newPos = new Position(here.x-1, here.y) ;
            newPath = path ;
            newPath.add (newPos) ;
            findPath(newPath, finalPath) ;
        }

        if (here.x < 4 && matrix[here.x+1][here.y] > matrix[here.x][here.y]) {
            // we can move right
            newPos = new Position(here.x+1, here.y) ;
            newPath = path ;
            newPath.add (newPos) ;
            findPath(newPath, finalPath) ;
        }

        if (here.y > 0 && matrix[here.x][here.y-1] > matrix[here.x][here.y]) {
            // we can move up
            newPos = new Position(here.x, here.y-1) ;
            newPath = path ;
            newPath.add (newPos) ;
            findPath(newPath, finalPath) ;
        }

        if (here.y < 5 && matrix[here.x][here.y+1] > matrix[here.x][here.y]) {
            // we can move down
            newPos = new Position(here.x, here.y+1) ;
            newPath = path ;
            newPath.add (newPos) ;
            findPath(newPath, finalPath) ;
        }
    }
}

这是python中相同算法的测试版本。 (我注意到使用x, y作为坐标有点误导。x实际上是“垂直的”而y是“水平的”,数组的索引方式就是它。我已经设置了一个矩阵,有四条通往出口的路径和几条死路。)

import copy, sys

matrix = [
        [5,  13, 17, 58,   2], 
        [17, 24, 32,  3,  24],
        [23,  7, 33,  1,   7],
        [45, 40, 37, 38,  70],
        [47, 34, 12, 25,   2],
        [52, 56, 68, 76, 100]]

def showPath(path):
    for position in path:
        sys.stdout.write("(" + str(position[0]) + ", " + str(position[1]) + "), ")
    sys.stdout.write("\n\n")
    sys.stdout.flush()

def findPath(path):
    #showPath(path)
    global finalPath
    x = path[-1][0]
    y = path[-1][1]
    if x == 5 and y == 4:
        showPath(path)
        if len(finalPath) == 0 or len(finalPath) > len (path):
            finalPath[:] = copy.deepcopy(path)
        return
    if x > 0 and matrix[x-1][y] > matrix[x][y]:
        # we can move up
        newPath = copy.deepcopy(path)
        newPath.append([x-1, y])
        findPath(newPath)
    if x < 5 and matrix[x+1][y] > matrix[x][y]:
        # we can move down
        newPath = copy.deepcopy(path)
        newPath.append([x+1, y])
        findPath(newPath)
    if y > 0 and matrix[x][y-1] > matrix[x][y]:
        # we can move left
        newPath = copy.deepcopy(path)
        newPath.append([x, y-1])
        findPath(newPath)
    if y < 4 and matrix[x][y+1] > matrix[x][y]:
        # we can move right
        newPath = copy.deepcopy(path)
        newPath.append([x, y+1])
        findPath(newPath)

path = []
path.append([0, 0])
finalPath = []
findPath(path)
print "Shortest Path: " + str(len(finalPath)) + " steps.\n"
showPath(finalPath)

如果您取消注释showPath()中的第一个findPath()来电,您可以看到每一步,看看死胡同被放弃的地方。如果只显示到达出口的路径,则输出如下所示:

(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (5, 0), (5, 1), (5, 2), (5, 3), (5, 4), 
(0, 0), (1, 0), (1, 1), (1, 2), (2, 2), (3, 2), (3, 1), (3, 0), (4, 0), (5, 0), (5, 1), (5, 2), (5, 3), (5, 4), 
(0, 0), (0, 1), (1, 1), (1, 2), (2, 2), (3, 2), (3, 1), (3, 0), (4, 0), (5, 0), (5, 1), (5, 2), (5, 3), (5, 4), 
(0, 0), (0, 1), (0, 2), (1, 2), (2, 2), (3, 2), (3, 1), (3, 0), (4, 0), (5, 0), (5, 1), (5, 2), (5, 3), (5, 4), 
Shortest Path: 10 steps.
(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (5, 0), (5, 1), (5, 2), (5, 3), (5, 4),

答案 2 :(得分:0)

在这里,您可以为所有可能性构建一棵树,然后采用最短的树。内部有一个循环用于跟踪结果,但你也可以用一些丑陋的ifs来解决这个问题......

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

public class BetterPathfinder {

    public class Comperator implements Comparator<Path> {

        @Override
        public int compare(Path o1, Path o2) {
            return o1.getValue().compareTo(o2.getValue());
        }
    }

    public class Path {

        private Integer lenght;
        TreeMap<Integer, String> trace = new TreeMap<>();

        public Path(int lenght) {
            this.lenght = lenght;
        }

        public Path(Path find, int i, int j) {
            this.lenght = find.getValue() + 1;
            this.trace.putAll(find.getTrace());

            this.trace.put(lenght, "(" + i + "," + j + ")");
        }

        private Map<Integer, String> getTrace() {
            return trace;
        }

        public Integer getValue() {
            return lenght;
        }

        @Override
        public String toString() {
            String res = "end";
            for (Entry<Integer, String> is : trace.entrySet()) {
                res = is.getValue() + "->" + res;
            }
            return res;
        }

    }

    private int[][] matrix;
    private int matrixLenghtI;
    private int matrixLenghtJ;

    public BetterPathfinder(int[][] matrix, int matrixLenghtI, int matrixLenghtJ) {

        this.matrix = matrix;
        this.matrixLenghtI = matrixLenghtI;
        this.matrixLenghtJ = matrixLenghtJ;

    }

    public static void main(String[] args) {

        int matrixLenghtI = 6;
        int matrixLenghtJ = 5;

        int[][] matrix1 = { { 3, 13, 15, 28, 30 }, { 40, 51, 52, 29, 30 }, { 28, 10, 53, 54, 54 },
                { 53, 12, 55, 53, 60 }, { 70, 62, 56, 20, 80 }, { 80, 81, 90, 95, 100 } };

        int[][] matrix2 = { { 5, 13, 2, 5, 2 }, { 58, 24, 32, 3, 24 }, { 2, 7, 33, 1, 7 }, { 45, 40, 37, 24, 70 },
                { 47, 34, 12, 25, 2 }, { 52, 56, 68, 76, 100 } };

        BetterPathfinder finder1 = new BetterPathfinder(matrix1, matrixLenghtI, matrixLenghtJ);
        finder1.run();

        BetterPathfinder finder2 = new BetterPathfinder(matrix2, matrixLenghtI, matrixLenghtJ);
        finder2.run();
    }

    private void run() {
        int i = 0;
        int j = 0;

        System.out.println(new Path(find(i, j), i, j));
    }

    private Path find(int i, int j) {
        int value = matrix[i][j];
        int[] next = { i, j };

        ArrayList<Path> test = new ArrayList<>();

        if (i == matrixLenghtI - 1 && j == matrixLenghtJ - 1)
            return new Path(1);

        if (i > 0 && matrix[i - 1][j] > value) {
            next[0] = i - 1;
            next[1] = j;

            test.add(new Path(find(next[0], next[1]), next[0], next[1]));
        }
        if (j > 0 && matrix[i][j - 1] > value) {
            next[0] = i;
            next[1] = j - 1;
            test.add(new Path(find(next[0], next[1]), next[0], next[1]));
        }
        if (i < matrixLenghtI - 1 && matrix[i + 1][j] > value) {
            next[0] = i + 1;
            next[1] = j;
            test.add(new Path(find(next[0], next[1]), next[0], next[1]));
        }
        if (j < matrixLenghtJ - 1 && matrix[i][j + 1] > value) {
            next[0] = i;
            next[1] = j + 1;
            test.add(new Path(find(next[0], next[1]), next[0], next[1]));
        }

        if (test.isEmpty()) {
            return new Path(100);
        }

        return Collections.min(test, new Comperator());
    }
}

结果:

(0,0)->(1,0)->(1,1)->(1,2)->(2,2)->(3,2)->(4,2)->(5,2)->(5,3)->(5,4)->end
(0,0)->(0,1)->(1,1)->(1,2)->(2,2)->(3,2)->(3,1)->(3,0)->(4,0)->(5,0)->(5,1)->(5,2)->(5,3)->(5,4)->end

答案 3 :(得分:0)

你想要一个递归策略。一个非常简单但很昂贵的方法就是简单地充斥电路板。类似&#34;尝试每条可能的路径并计算距离&#34;

你可以通过想象移动卵石来递归地做到这一点。

public int shortestPath(Point src, Point dest) {
    if (src.equals(dest)) {
            return 0;
    }

    // You need to do some bound checks here
    int left = shortestPath(new Point(src.x - 1, src.y), dest);
    int right = shortestPath(new Point(src.x + 1, src.y), dest);
    int up = shortestPath(new Point(src.x, src.y + 1), dest);
    int down = shortestPath(new Point(src.x, src.y - 1), dest);

    // Decide for the direction that has the shortest path
    return min(left, right, up, down) + 1;
}

如果您对解决方案所代表的路径感兴趣,则可以在创建时跟踪路径。为此,您只需要保存min确定的方向。

我需要在我的计算机科学研究中解决类似的任务。我们需要计算knight chess board对达到给定destination所需的最短移动量。也许这也可以帮助你:http://pastebin.com/0xwMcQgj

答案 4 :(得分:0)

职位等级:

/**
 * Represents a position in the matrix.
 */
public class Position {

    final private int x;
    final private int y;

    public Position(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    @Override
    public String toString() {
        return "(" + x + ", " + y + ')';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Position position = (Position) o;

        if (x != position.x) return false;
        return y == position.y;

    }

    @Override
    public int hashCode() {
        int result = x;
        result = 31 * result + y;
        return result;
    }
}

董事会成员:

/**
 * A board represents all of the locations in the matrix.  It provides a simple interface to getting
 * the value in a position, and tracking the height and width of the matrix.
 */
public class Board {
    final int [][] board;

    public Board(int[][] board) {
        this.board = board;
    }

    final int positionValue(Position position) {
        return this.board[position.getY()][position.getX()];
    }

    final int getWidth() {
        return board[0].length;
    }

    final int getHeight() {
        return board.length;
    }
}

路径查找器类:

import java.util.ArrayList;
import java.util.List;

/**
 * Find the shortest path from a starting point to ending point in a matrix, assuming you can
 * only move to a position with a greater value than your current position.
 */
public class PathFinder {

    final private Board board;
    final private Position start;
    final private Position end;


    public PathFinder(Board board, int startX, int startY, int endX, int endY) {
        this.board = board;
        this.start = new Position(startX, startY);
        this.end = new Position(endX, endY);
    }

    /**
     * Gets the shortest path from the start to end positions.  This method
     * takes all of the paths, then determines which one is shortest and returns that.
     *
     * @return the shortest path from the start to end positions.
     */
    public List<Position> shortestPath() {

        List<List<Position>> allPaths = this.getAllPaths();

        System.out.println("Paths found: " + allPaths.size());
        List<Position> shortestPath = null;

        for (List<Position> path : allPaths) {
            if (shortestPath == null) {
                shortestPath = path;
            }
            else if (shortestPath.size() > path.size()) {
                shortestPath = path;
            }
        }

        return shortestPath;
    }

    /**
     * Convenience method for starting the getAllPaths process.
     *
     * @return all of the paths from the start to end positions
     */
    private List<List<Position>> getAllPaths() {
        List<List<Position>> paths = new ArrayList<List<Position>>();
        return this.getAllPaths(paths, new ArrayList<Position>(), start);
    }

    /**
     * Gets all of the paths from the start to end position.  This is   done recursively by visiting every
     * position, while following the rules that you can only move to a  position with a value greater
     * than the position you're currently on.  When reaching the end position, the path is added to
     * the list of all found paths, which is returned.
     *
     * @param paths the current list of all found paths.
     * @param path the current path
     * @param position the current position
     * @return all paths from the start to end positions
     */
    private List<List<Position>> getAllPaths(List<List<Position>> paths, List<Position> path, Position position) {
        path.add(position);
        if (position.equals(end)) {
            paths.add(path);
            return paths;
        }

        //x+
        if (position.getX() + 1 < board.getWidth()) {
            Position xp = new Position(position.getX() + 1, position.getY());
            if (board.positionValue(position) < board.positionValue(xp)) {
                getAllPaths(paths, new ArrayList<Position>(path), xp);
            }
        }
        //x-
        if (position.getX() - 1 >= 0) {
            Position xm = new Position(position.getX() - 1, position.getY());
            if (board.positionValue(position) < board.positionValue(xm)) {
                getAllPaths(paths, new ArrayList<Position>(path), xm);
            }
        }
        //y+
        if (position.getY() + 1 < board.getHeight()) {
            Position yp = new Position(position.getX(), position.getY() + 1);
            if (board.positionValue(position) < board.positionValue(yp)) {
                getAllPaths(paths, new ArrayList<Position>(path), yp);
            }
        }
        //y-
        if (position.getY() - 1 >= 0) {
            Position ym = new Position(position.getX(), position.getY() - 1);
            if (board.positionValue(position) < board.positionValue(ym)) {
                getAllPaths(paths, new ArrayList<Position>(path), ym);
            }
        }

        return paths;
    }

    /**
     * Run the example then print the results.
     *
     * @param args na
     */
    public static void main(String[] args) {
        int [][] array = {{5, 13, 2, 5, 2},
                            {14, 24, 32, 3, 24},
                            {15, 7, 33, 1, 7},
                            {45, 40, 37, 24, 70},
                            {47, 34, 12, 25, 2},
                            {52, 56, 68, 76, 100}
        };

        final Board board = new Board(array);
        final Position end = new Position(board.getWidth()-1, board.getHeight() - 1);
        final PathFinder pathFinder = new PathFinder(board, 0, 0, board.getWidth()-1, board.getHeight()-1);

        final List<Position> path = pathFinder.shortestPath();

        System.out.println("Shortest Path: ");
        for (Position position : path) {
            if (!position.equals(end)) {
                System.out.print(position + " -> ");
            }
            else {
                System.out.println(position);
            }
        }
        System.out.println();
    }
}

答案 5 :(得分:0)

public class shortestPath{
public static int shortestPath(int[][] mat){
    if(mat == null || mat.length == 0 || mat[0].length == 0)
        return 0;
    else {
        int n = shortestPath(mat, 0, 0, 0);
        return (n == mat.length*mat.length+1 ) ? 0 : n;
    }
}

private static int shortestPath(int[][]mat, int row, int col,int prev){

    if (!valid(mat,row,col) || !(mat[row][col] > prev)){
        return mat.length*mat.length+1;
    } else if(row == mat.length - 1 && col == mat[row].length - 1) {
        return 1;
    } else {
        return minimum(shortestPath(mat,row-1,col, mat[row][col]), 
            shortestPath(mat,row+1,col, mat[row][col]),
            shortestPath(mat,row,col-1, mat[row][col]),
            shortestPath(mat,row,col+1, mat[row][col])) + 1;
    }
}

private static boolean valid(int[][]mat,int row, int col){
    if(row < 0 || col < 0 || col > mat[0].length-1 || row > mat.length-1)
        return false;
    else
        return true;
}

private static int minimum(int x, int y, int t, int z){
    int min1 = (x > y)? y : x;
    int min2 = (t > z)? z : t;

    return (min1 > min2)? min2 : min1;
}

public static void main(String[] args){

    int maze[][] = {
            {  3, 13, 15, 28, 30},
            { 40, 51, 52, 29, 30},
            { 28, 10, 53, 54, 53},
            { 53, 12, 55, 53, 60},
            { 70, 62, 56, 20, 80},
            { 81, 81, 90, 95, 100}};

    System.out.println(shortestPath(maze));
}

}

答案 6 :(得分:0)

这是我解决它的方法,注意在你的例子中我们应该得到 16

public static void main(String[] args)
{
    int[][] mat = 
        { 
                { 3, 13, 15, 28, 30 }, 
                { 40, 51, 52, 29, 30 }, 
                { 28, 10, 53, 54, 53 }, 
                { 53, 12, 55, 53, 60 },
                { 70, 62, 56, 20, 80 }, 
                { 80, 81, 90, 95, 100 } 
        };
    System.out.println(shortestPath(mat)); // 10
    
    int[][] mat1 = 
        {
            {0,   1,   2,   3,   4 },
            {0,   5,   13,  2,   5,   2}, 
            {1,   58,  24,  32,  3,   24} ,
            {2,   2 ,  7,   33,  1,   7} ,
            {3,   45,  40,  37,  24,  70},
            {4,   47,  34,  12,  25,  2}, 
            {5,   52,  56,  68,  76,  100}
        };
    
    System.out.println(shortestPath(mat1)); // 16
}

public static int shortestPath(int[][] mat)
{
    return shortestPath(mat, 0, 0, mat[0][0] - 1, 0);
}

private static int shortestPath(int[][] mat, int row, int col, int prev, int counter)
{
    if (row < 0 || row == mat.length || col < 0 || col == mat[row].length) // boundaries
        return Integer.MAX_VALUE;

    if (mat[row][col] <= prev || mat[row][col] == -999) // if the sequence is not ascending or if we have been in this cell before
        return Integer.MAX_VALUE;

    if (row == mat.length - 1 && col == mat[row].length - 1)
        return counter + 1;

    int temp = mat[row][col];
    mat[row][col] = -999;

    int up    = shortestPath(mat, row - 1, col, temp, counter + 1); // go up and count
    int down  = shortestPath(mat, row + 1, col, temp, counter + 1);
    int left  = shortestPath(mat, row, col - 1, temp, counter + 1);
    int right = shortestPath(mat, row, col + 1, temp, counter + 1);

    mat[row][col] = temp;

    return Math.min(Math.min(up, down), Math.min(left, right)); // get the min
}