【Py/Java/C++三种语言OD2023C卷真题】20天拿下华为OD笔试之【BFS】2023C-周末爬山【欧弟算法】全网注释最详细分类最全的华为OD真题题解

文章目录

  • 题目描述与示例
    • 题目描述
      • 输入描述
      • 输出描述
    • 示例1
      • 输入
      • 输入
      • 说明
    • 示例2
      • 输入
      • 输入
      • 说明
  • 解题思路
  • 代码
    • Python
    • Java
    • C++
    • 时空复杂度
  • 华为OD算法/大厂面试高频题算法练习冲刺训练

题目描述与示例

题目描述

周末小明准备去爬山锻炼,0代表平地,山的高度使用19来表示,小明每次爬山或下山高度只能相差kk以内,每次只能上下左右一个方向上移动一格,小明从左上角(0,0)位置出发

输入描述

第一行输入m n k(空格分隔)

代表 m*n 的二维山地图,k为小明每次爬山或下山高度差的最大值,然后接下来输入山地图,一共 mn列,均以空格分隔。

取值范围: 0 < m ≤ 500

0 < n ≤ 500
0 < k < 5

输出描述

请问小明能爬到的最高峰多高,到该最高峰的最短步数,输出以空格分隔。

同高度的山峰输出较短步数。

如果没有可以爬的山峰,则高度和步数都返回0

备注:所有用例输入均为正确格式,且在取值范围内,考生不需要考虑不合法的输入格式。

示例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

说明

根据山地图可知,能爬到的最高峰在(0,2)位置,高度为2,最短路径为(0,0)-(0,1)-(0,2),最短步数为2

示例2

输入

5 4 3
0 0 0 0
0 0 0 0
0 9 0 0
0 0 0 0
0 0 0 9

输入

0 0

说明

根据山地图可知,每次爬山距离3,无法爬到山峰上,步数为0

解题思路

又是二维网格状无向图的搜索问题。

题目包含两个设问:找到最高峰和到达最高峰的最短路径。

找到最高峰的问题可以用DFS也可以用BFS解决,但是最短路径问题只能用BFS解决(回溯可以解决但是会超时)。

综上,可以用一次BFS就同时完成最高峰和最短路径的搜索。

代码

Python

# 题目:【BFS】2023C-周末爬山
# 分值:200
# 作者:许老师-闭着眼睛学数理化
# 算法:BFS
# 代码看不懂的地方,请直接在群上提问


from collections import deque
from math import inf


# 四个方向数组
DIERECTIONS = [(0,1), (1,0), (-1,0), (0,-1)]

# 输入长、宽、最大高度差
m, n, k = map(int, input().split())
# 初始化地图
grid = list()
for _ in range(m):
    grid.append(list(map(int, input().split())))

# 初始化BFS搜索层数,表示最短路径大小
level = 0
# 初始化全局的最高山峰高度,为起点的高度
highest_hill = grid[0][0]
# 初始化全局的到达最高山峰的最短路径
shortest_route = 0

# 初始化检查数组
check_list = [[0] * n for _ in range(m)]
# 起点设置为已检查过
check_list[0][0] = 1
# 初始化维护BFS的队列
q = deque()
# 起始位置只包含左上角的(0, 0)
q.append((0, 0))

# 进行BFS
while q:
    # 搜索层数+1
    level += 1
    qSize = len(q)
    for _ in range(qSize):
        x, y = q.popleft()
        # 四个近邻点
        for dx, dy in DIERECTIONS:
            nx, ny = x+dx, y+dy
            # 三个条件:
            # 1.未越界;2.未检查;3.当前点和近邻点之间高度差小于k
            if 0 <= nx < m and 0 <= ny < n and check_list[nx][ny] == 0 and abs(grid[nx][ny]-grid[x][y]) <= k:
                q.append((nx, ny))
                check_list[nx][ny] = 1
                # 如果该近邻点的高度大于全局最高山峰的高度
                # 则更新highest_hill和shortest_route
                if grid[nx][ny] > highest_hill:
                    highest_hill = grid[nx][ny]
                    shortest_route = level

print(highest_hill, shortest_route)

Java

import java.util.*;

public class Main {
    static int[][] DIRECTIONS = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}};

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int m = scanner.nextInt();
        int n = scanner.nextInt();
        int k = scanner.nextInt();

        int[][] grid = new int[m][n];
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                grid[i][j] = scanner.nextInt();
            }
        }

        int level = 0;
        int highestHill = grid[0][0];
        int shortestRoute = 0;

        int[][] checkList = new int[m][n];
        checkList[0][0] = 1;
        Queue<int[]> queue = new LinkedList<>();
        queue.add(new int[]{0, 0});

        while (!queue.isEmpty()) {
            level++;
            int qSize = queue.size();
            for (int i = 0; i < qSize; ++i) {
                int[] point = queue.poll();
                int x = point[0];
                int y = point[1];
                for (int[] dir : DIRECTIONS) {
                    int nx = x + dir[0];
                    int ny = y + dir[1];
                    if (0 <= nx && nx < m && 0 <= ny && ny < n && checkList[nx][ny] == 0 && Math.abs(grid[nx][ny] - grid[x][y]) <= k) {
                        queue.add(new int[]{nx, ny});
                        checkList[nx][ny] = 1;
                        if (grid[nx][ny] > highestHill) {
                            highestHill = grid[nx][ny];
                            shortestRoute = level;
                        }
                    }
                }
            }
        }

        System.out.println(highestHill + " " + shortestRoute);
    }
}

C++

#include 
#include 
#include 
#include 

using namespace std;

vector<pair<int, int>> DIRECTIONS = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}};

int main() {
    int m, n, k;
    cin >> m >> n >> k;

    vector<vector<int>> grid(m, vector<int>(n));
    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < n; ++j) {
            cin >> grid[i][j];
        }
    }

    int level = 0;
    int highestHill = grid[0][0];
    int shortestRoute = 0;

    vector<vector<int>> checkList(m, vector<int>(n));
    checkList[0][0] = 1;
    queue<pair<int, int>> q;
    q.push({0, 0});

    while (!q.empty()) {
        level++;
        int qSize = q.size();
        for (int i = 0; i < qSize; ++i) {
            int x = q.front().first;
            int y = q.front().second;
            q.pop();
            for (auto& dir : DIRECTIONS) {
                int nx = x + dir.first;
                int ny = y + dir.second;
                if (0 <= nx && nx < m && 0 <= ny && ny < n && checkList[nx][ny] == 0 && abs(grid[nx][ny] - grid[x][y]) <= k) {
                    q.push({nx, ny});
                    checkList[nx][ny] = 1;
                    if (grid[nx][ny] > highestHill) {
                        highestHill = grid[nx][ny];
                        shortestRoute = level;
                    }
                }
            }
        }
    }

    cout << highestHill << " " << shortestRoute << endl;

    return 0;
}

时空复杂度

时间复杂度:O(NM)

空间复杂度:O(NM)


华为OD算法/大厂面试高频题算法练习冲刺训练

  • 华为OD算法/大厂面试高频题算法冲刺训练目前开始常态化报名!目前已服务100+同学成功上岸!

  • 课程讲师为全网50w+粉丝编程博主@吴师兄学算法 以及小红书头部编程博主@闭着眼睛学数理化

  • 每期人数维持在20人内,保证能够最大限度地满足到每一个同学的需求,达到和1v1同样的学习效果!

  • 60+天陪伴式学习,40+直播课时,300+动画图解视频,300+LeetCode经典题,200+华为OD真题/大厂真题,还有简历修改、模拟面试、专属HR对接将为你解锁

  • 可上全网独家的欧弟OJ系统练习华子OD、大厂真题

  • 可查看链接 大厂真题汇总 & OD真题汇总(持续更新)

  • 绿色聊天软件戳 od1336了解更多

你可能感兴趣的:(最新华为OD真题,#,BFS,算法,java,c++,python,华为od,宽度优先)