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

可上 欧弟OJ系统 练习华子OD、大厂真题
绿色聊天软件戳 od1441了解算法冲刺训练(备注【CSDN】否则不通过)

相关推荐阅读

从2024年8月14号开始,OD机考全部配置为2024E卷
注意几个关键点:

  1. 大部分的题目仍为往期2023A+B+C以及2024D的旧题。注意万变不离其宗,把方法掌握,无论遇到什么题目都可以轻松应对。
  2. 支持多次提交题目,以最后一次提交为准。可以先做200的再做100的,然后可以反复提交。
  3. E卷仍然为单机位+屏幕监控的形式进行监考。
  4. 进入考试界面新加入了这样一段话并且用红字标出,可以看出华子对作弊代考等行为是0容忍的,请各位同学认真学习,不要妄图通过其他违规途径通过考试。
    在这里插入图片描述

题目描述与示例

题目描述:

周末小明准备去爬山锻炼,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) if highest_hill > grid[0][0] else print(0, 0)

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;
                        }
                    }
                }
            }
        }
        if (highestHill > grid[0][0]){
            System.out.println(highestHill + " " + shortestRoute);
        }
        else{
            System.out.println("0 0");
        }
    }
}

cpp

#include <iostream>
#include <vector>
#include <queue>
#include <cmath>

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;
                    }
                }
            }
        }
    }
    if (highestHill > grid[0][0]){
            cout << highestHill << " " << shortestRoute << endl;
        }
    else{
        cout << "0 0" << endl;
    }    
    return 0;
}

时空复杂度

时间复杂度:O(NM)

空间复杂度:O(NM)


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

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

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

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

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

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

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

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

  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
华为od机试中,新学校选址问题是一个关于使用Java语言解决的问题。在解决这个问题时,我们可以通过以下步骤来完成。 首先,我们需要理解问题的要求和限制条件。新学校选址的目标是在一个给定的地图上找到一个合适的位置来建设新学校。这个位置应满足一定的条件,比如与周围的住宅区距离不宜过远,应尽可能靠近居民区。限制条件可能还包括学校面积和周边环境等。 接下来,我们需要获取地图的数据。可以通过读取一个地图文件或者从数据库中查询地图数据来获得地图的信息。地图数据的存储方式可以灵活选择,比如使用二维数组或者邻接矩阵。 然后,我们需要编写一个Java程序来实现新学校选址算法。可以使用图的遍历算法,比如深度优先搜索(DFS)或广度优先搜索(BFS)来实现。算法的核心是通过递归或循环遍历地图上的每一个位置,并根据选址条件进行判断和筛选。 最后,我们需要输出选址结果。可以将选定的位置以某种方式标记在地图上,比如输出一个新的地图文件或者在图形界面中显示。同时,还可以输出选址的具体坐标和其他相关信息,以便后续的学校建设工作。 总之,通过使用Java语言,我们可以通过一个新学校选址问题来展示我们在算法设计和编程方面的能力。相信在华为od机试中,通过合理的数据处理和算法实现,我们可以解决这个问题并得出满意的选址结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

闭着眼睛学算法

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值