华为OD机试 2024E卷题库疯狂收录中,刷题点这里
专栏导读
本专栏收录于《华为OD机试(JAVA)真题(E卷+D卷+A卷+B卷+C卷)》。
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。
一、题目描述
周末小明准备去爬山锻炼,0代表平地,山的高度使用1到9来表示,小明每次爬山或下山高度只能相差k及k以内,每次只能上下左右一个方向上移动一格,小明从左上角(0,0)位置出发
二、输入描述
第一行输入n m k(空格分隔)
代表n*m的二维山地图,k为小明每次爬山或下山高度差的最大值,然后接下来输入山地图,一共m行n列,均以空格分隔。取值范围:
0 < m <= 500
0 < n <= 500
0 < k <= 5
备注
所有用例输入均为正确格式,且在取值范围内,考生不需要考虑输入格式非法的情况。
三、输出描述
请问小明能爬到的最高峰是多少, 到该最高峰的最短步数,输出以空格分隔。
同高度的山峰输出较小步数。
如果没有可以爬的山峰,则高度和步数均返回0
四、测试用例
测试用例1:
1、输入
5 4 1
0 1 2 0
1 0 0 0
1 0 1 2
1 3 1 0
0 0 0 9
2、输出
2 2
3、说明
根据山地图可知,能爬到的最高峰在(0,2)位置,高度为2,最短路径为(0,0)-(0,1)-(0,2),最短步数为2。
测试用例2:
1、输入
5 4 3
0 0 0 0
0 0 0 0
0 9 0 0
0 0 0 0
0 0 0 9
2、输出
0 0
3、说明
根据山地图可知,每次爬山距离3,无法爬到山峰上,步数为0。
五、解题思路
本题是一个典型的二维网格搜索问题。小明从地图的左上角(0, 0)出发,每次只能上下左右移动一格,爬山或下山的高度差不能超过k。那么这就是一个 广度优先搜索(BFS) 问题,我们可以使用BFS遍历整个地图,记录每个位置的最短步数和能达到的最高峰值。
具体步骤如下:
- 初始化:从起点(0, 0)开始,将其加入队列,同时记录步数。
- BFS搜索:利用队列每次取出当前位置,尝试向上下左右四个方向移动,判断是否可以移动。如果可以移动,则记录该位置的步数并加入队列。
- 高度条件判断:每次移动时需要判断目标位置的高度与当前高度差是否在k的范围内。
- 结果记录:在遍历过程中记录最高峰及其最短步数,最终输出结果。如果没有可爬的山峰,则输出高度和步数均为0。
六、Java算法源码
public class OdTest01 {
// 四个方向:上、下、左、右
private static final int[] dx = {-1, 1, 0, 0};
private static final int[] dy = {0, 0, -1, 1};
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 输入n、m、k
int n = scanner.nextInt();
int m = scanner.nextInt();
int k = scanner.nextInt();
// 输入山地图
int[][] map = new int[m][n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
map[i][j] = scanner.nextInt();
}
}
// 调用BFS方法寻找最高峰和最短步数
int[] result = bfs(map, m, n, k);
// 输出结果
System.out.println(result[0] + " " + result[1]);
}
/**
* BFS算法,找到可以达到的最高峰及最短步数
*/
private static int[] bfs(int[][] map, int m, int n, int k) {
// 队列用于BFS存储 [x坐标, y坐标, 当前步数]
Queue<int[]> queue = new LinkedList<>();
boolean[][] visited = new boolean[m][n]; // 记录是否访问过
queue.add(new int[]{0, 0, 0}); // 从左上角(0,0)出发,步数为0
visited[0][0] = true;
int maxHeight = map[0][0]; // 最高峰高度
int minSteps = 0; // 最短步数
while (!queue.isEmpty()) {
int[] current = queue.poll();
int x = current[0];
int y = current[1];
int steps = current[2];
// 尝试四个方向移动
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 (Math.abs(map[newX][newY] - map[x][y]) <= k) {
visited[newX][newY] = true;
queue.add(new int[]{newX, newY, steps + 1});
// 更新最高峰和最短步数
if (map[newX][newY] > maxHeight) {
maxHeight = map[newX][newY];
minSteps = steps + 1;
} else if (map[newX][newY] == maxHeight && (steps + 1) < minSteps) {
minSteps = steps + 1;
}
}
}
}
}
// 如果最高峰和起点相同(即无法爬山),返回高度和步数为0
if (maxHeight == map[0][0]) {
return new int[]{0, 0};
}
return new int[]{maxHeight, minSteps};
}
}
七、效果展示
1、输入
3 3 1
0 1 0
9 0 9
0 1 0
2、输出
1 1
3、说明
小明从左上角(0,0)出发,只能到达(0,1),最高峰为1,最短步数为1。
由于相邻的高度差过大(k=1的限制),他无法继续爬到其他位置。
🏆下一篇:华为OD机试 - 简易内存池 - 逻辑分析(Java 2024 E卷 200分)
🏆本文收录于,华为OD机试(JAVA)真题(E卷+D卷+A卷+B卷+C卷)
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。