import java.util.*;


public class Solution {
    // 自定义坐标信息结构类
    public class Info {
        public int x;
        public int y;
        public Info(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 递增路径的最大长度
     * @param matrix int整型二维数组 描述矩阵的每个数
     * @return int整型
     */
    public int solve (int[][] matrix) {
        // write code here

        // 算法思路:采用基于【地图标记】的【记忆化搜索】,整体可参考【岛屿问题】

        // 调用递归函数 - 遍历数组
        int[][] arrived = new int[matrix.length][matrix[0].length];
        int max = 0;
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[0].length; j++) {
                if (arrived[i][j] == 0) {
                    // 当前路径没有被访问过,则开启搜索
                    Info curInfo = new Info(i, j);
                    int result = process(matrix, arrived, curInfo);
                    if (result > max) {
                        max = result;
                    }
                }
            }
        }
        return max;
    }

    // 设计递归函数
    // 返回值:当前位置距离终点的路径长度(包含自身)
    // 参数:矩阵、已走过位置矩阵、当前位置
    public int process(int[][] matrix, int[][] arrived, Info curLocation) {
        // 记录当前位置
        int curX = curLocation.x;
        int curY = curLocation.y;
        int cur = matrix[curX][curY];
        int limitX = matrix.length;
        int limitY = matrix[0].length;

        // 设置一个可达坐标队列,记录当前位置可以走向的下一个位置
        Queue<Info> accessible = new LinkedList<>();
        // 上 - x-1
        if ((curX - 1) >= 0 && cur < matrix[curX - 1][curY]) {
            accessible.add(new Info(curX - 1, curY));
        }
        // 下 - x+1
        if ((curX + 1) < limitX && cur < matrix[curX + 1][curY]) {
            accessible.add(new Info(curX + 1, curY));
        }
        // 左 - y-1
        if ((curY - 1) >= 0 && cur < matrix[curX][curY - 1]) {
            accessible.add(new Info(curX, curY - 1));
        }
        // 右 - y+1
        if ((curY + 1) < limitY && cur < matrix[curX][curY + 1]) {
            accessible.add(new Info(curX, curY + 1));
        }

        // 递归出口
        if (accessible.size() == 0) {
            // 代表没办法接着走了,返回当前位置为路径中唯一的位置(1),并记录arrived
            arrived[curX][curY] = 1;
            return 1;
        }

        // 分支限界 - 记忆化搜索
        int maxLong = 0;
        for (Info next : accessible) {
            // 记忆化搜索 - 若next位置在arrived有记录则直接采用记录即可
            int pathLong = 0;
            if (arrived[next.x][next.y] > 0) {
                pathLong = arrived[next.x][next.y];
            } else {
                // 否则记录调用递归
                pathLong = process(matrix, arrived, next);
            }
            // 更新最大值
            if (pathLong > maxLong) {
                maxLong = pathLong;
            }
        }
        // 当前位置的路径最大长度为四周可走位置的路径的最大值+自己这个位置(1)
        arrived[curX][curY] = maxLong + 1;
        return maxLong + 1;
    }
}