整体思路概述
要解决小U在地图上移动以获取最大移动次数的问题,核心在于找出所有可能的移动路径,并从中挑选出长度最长的路径。由于地图上每个位置都可能是起始点,且从每个起始点出发都有多种移动选择,这就需要对各种可能性进行全面的探索。深度优先搜索(DFS)是一种非常适合处理此类路径探索问题的算法,它能够沿着一条路径尽可能深地搜索下去,直到无法继续,然后回溯到上一个节点,尝试其他可能的路径。
具体步骤分析
1. 初始化部分
boolean[][] visited = new boolean[m][n];
int maxCount = 0;
- 创建一个与地图大小相同的二维布尔数组
visited,用于记录地图上每个位置是否已经被访问过。这是为了确保每个位置只能经过一次,符合题目要求。 - 初始化一个变量
maxCount为 0,用于存储找到的最大移动次数。
2. 遍历所有可能的起始位置
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
maxCount = Math.max(maxCount, dfs(i, j, a, visited, true, 1));
maxCount = Math.max(maxCount, dfs(i, j, a, visited, false, 1));
}
}
- 使用两层嵌套的
for循环遍历地图上的每一个位置(i, j)。 - 对于每个位置,分别以“下一步是上坡”(
isUp = true)和“下一步是下坡”(isUp = false)两种情况调用dfs方法进行深度优先搜索。 - 在每次调用
dfs方法后,使用Math.max函数更新maxCount,确保maxCount始终存储着当前找到的最大移动次数。
3. 深度优先搜索(DFS)方法
private static int dfs(int x, int y, int[][] a, boolean[][] visited, boolean isUp, int count) {
int m = a.length;
int n = a[0].length;
visited[x][y] = true;
int maxCount = count;
int[] dx = {0, 0, 1, -1};
int[] dy = {1, -1, 0, 0};
for (int i = 0; i < 4; i++) {
int newX = x + dx[i];
int newY = y + dy[i];
if (newX >= 0 && newX < m && newY >= 0 && newY < n &&!visited[newX][newY]) {
if (isUp && a[newX][newY] < a[x][y]) {
maxCount = Math.max(maxCount, dfs(newX, newY, a, visited, false, count + 1));
} else if (!isUp && a[newX][newY] > a[x][y]) {
maxCount = Math.max(maxCount, dfs(newX, newY, a, visited, true, count + 1));
}
}
}
visited[x][y] = false;
return maxCount;
}
- 参数说明:
x和y表示当前所在位置的坐标。a是存储地图每个位置高度信息的二维数组。visited是用于记录位置访问状态的二维布尔数组。isUp表示上一步移动是否为上坡,用于判断下一步移动的合法性。count表示当前已经走过的位置数量。
- 核心逻辑:
- 首先将当前位置
(x, y)标记为已访问。 - 初始化从当前位置开始能达到的最大移动次数
maxCount为当前的移动次数count。 - 定义四个方向的偏移量数组
dx和dy,分别表示右、左、下、上四个方向。 - 使用
for循环遍历这四个方向,计算新位置的坐标(newX, newY)。 - 检查新位置是否在地图范围内且未被访问过:
- 如果上一步是上坡(
isUp = true),且新位置的高度小于当前位置的高度,说明可以下坡移动,递归调用dfs方法,将isUp置为false(表示下一步要下坡),并将移动次数加 1。 - 如果上一步是下坡(
isUp = false),且新位置的高度大于当前位置的高度,说明可以上坡移动,递归调用dfs方法,将isUp置为true(表示下一步要上坡),并将移动次数加 1。 - 在每次递归调用后,使用
Math.max函数更新maxCount。
- 如果上一步是上坡(
- 最后将当前位置标记为未访问,这一步是回溯操作,以便后续其他路径可以访问该位置。
- 返回从当前位置开始能达到的最大移动次数。
- 首先将当前位置
全部代码
public static int solution(int m, int n, int[][] a) {
boolean[][] visited = new boolean[m][n];
int maxCount = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
maxCount = Math.max(maxCount, dfs(i, j, a, visited, true, 0));
maxCount = Math.max(maxCount, dfs(i, j, a, visited, false, 0));
}
}
// System.out.println("maxCount:"+maxCount);
// System.out.println("-----");
return maxCount;
}
private static int dfs(int x, int y, int[][] a, boolean[][] visited, boolean isUp, int count) {
int m = a.length;
int n = a[0].length;
visited[x][y] = true;
int maxCount = count;
int[] dx = {0, 0, 1, -1};
int[] dy = {1, -1, 0, 0};
for (int i = 0; i < 4; i++) {
int newX = x + dx[i];
int newY = y + dy[i];
if (newX >= 0 && newX < m && newY >= 0 && newY < n &&!visited[newX][newY]) {
if (isUp && a[newX][newY] < a[x][y]) {
maxCount = Math.max(maxCount, dfs(newX, newY, a, visited, false, count + 1));
} else if (!isUp && a[newX][newY] > a[x][y]) {
maxCount = Math.max(maxCount, dfs(newX, newY, a, visited, true, count + 1));
}
}
}
visited[x][y] = false;
return maxCount;
}