华为OD机试 - 可活动的最大网格点数目 - 广度优先搜索BFS(Python/JS/C/C++ 2024 E卷 200分)

在这里插入图片描述

华为OD机试 2024E卷题库疯狂收录中,刷题点这里

专栏导读

本专栏收录于《华为OD机试真题(Python/JS/C/C++)》

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。

一、题目描述

现有一个机器人,可放置于 M × N 的网格中任意位置,每个网格包含一个非负整数编号,当相邻网格的数字编号差的绝对值小于等于 1 时,机器人可以在网格间移动。

问题:求机器人可活动的最大范围对应的网格点数量。
说明:网格左上角坐标为(0,0),右下角坐标为(M-1,N-1),机器人只能在相邻网格间上下左右移动。

二、输入描述

第 1 行输入 M 和 N,M 表示网格的行数 N 表示网格的列数
之后 M 行表示网格数组,每行 N 个数值(数值为 0 到 5 之间),数值间用单个空格分隔,行与行无多余空格。

M、N、K 均为整数,且 1 ≤ M, N ≤ 150, 0 ≤ K ≤ 50

三、输出描述

输出 1 行,包含 1 个数字,表示最大活动区域的网格点数目,行首行尾无多余空格。

四、测试用例

测试用例1:

1、输入

4 4
1 2 5 2
2 4 4 5
3 5 7 1
4 6 2 4

2、输出

6

3、说明

相邻网格差值的绝对值都小于等于 1,且为最大区域,对应网格点数目为 6。

测试用例2:

1、输入

3 3
0 1 0
1 2 1
0 1 0

2、输出

9

3、说明

所有网格点的编号差的绝对值都不超过 1,整个网格都是一个连通区域,包含 9 个网格点。

五、解题思路

1、问题理解

给定一个 M × N 的网格,网格中的每个点有一个非负整数编号(0 到 5)。机器人可以在网格中任意放置起始点,然后在相邻的上下左右网格间移动,移动的条件是相邻网格编号的差的绝对值不超过 1。要求求出机器人在网格中可活动的最大范围,即能够到达的网格点的最大数量。

2、解决方案

为了求解这个问题,我们需要找到网格中最大的连通区域,其中相邻网格之间的编号差的绝对值不超过 1。这个问题可以转化为在图中寻找最大连通分量的问题,其中每个网格点是图中的一个节点,相邻的节点之间有边连接,前提是它们的编号差的绝对值不超过 1。

遍历网格中的每一个未被访问的点,使用 BFS 来找到与之相连的所有符合条件的点,记录下连通区域的大小,并更新最大连通区域的大小。

六、Python算法源码

# Python版本
import sys
from collections import deque

def main():
    # 读取所有输入
    input = sys.stdin.read().split()
    idx = 0
    # 读取网格的行数M和列数N
    M = int(input[idx])
    N = int(input[idx + 1])
    idx += 2
    # 初始化网格数组
    grid = []
    for _ in range(M):
        row = []
        for _ in range(N):
            row.append(int(input[idx]))
            idx += 1
        grid.append(row)
    # 初始化访问标记数组,全部设置为False
    visited = [[False for _ in range(N)] for _ in range(M)]
    max_region = 0  # 记录最大连通区域的大小
    # 定义四个方向的移动:上、下、左、右
    directions = [(-1,0), (1,0), (0,-1), (0,1)]
    # 遍历每一个网格点
    for i in range(M):
        for j in range(N):
            if not visited[i][j]:
                # 使用BFS计算当前连通区域的大小
                queue = deque()
                queue.append((i,j))
                visited[i][j] = True
                count = 1
                while queue:
                    x, y = queue.popleft()
                    for dx, dy in directions:
                        new_x = x + dx
                        new_y = y + dy
                        # 判断新位置是否在网格范围内且未被访问
                        if 0 <= new_x < M and 0 <= new_y < N and not visited[new_x][new_y]:
                            # 判断编号差的绝对值是否小于等于1
                            if abs(grid[x][y] - grid[new_x][new_y]) <= 1:
                                queue.append((new_x, new_y))
                                visited[new_x][new_y] = True
                                count += 1
                # 更新最大连通区域的大小
                if count > max_region:
                    max_region = count
    # 输出结果
    print(max_region)

if __name__ == "__main__":
    main()

七、JavaScript算法源码

// JavaScript版本
const readline = require('readline');

// 创建接口以逐行读取输入
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

let input = [];
rl.on('line', function(line){
    input = input.concat(line.trim().split(' '));
}).on('close', function(){
    let idx = 0;
    // 读取网格的行数M和列数N
    const M = parseInt(input[idx++]);
    const N = parseInt(input[idx++]);
    // 初始化网格数组
    let grid = [];
    for(let i = 0; i < M; i++){
        let row = [];
        for(let j = 0; j < N; j++){
            row.push(parseInt(input[idx++]));
        }
        grid.push(row);
    }
    // 初始化访问标记数组,全部设置为false
    let visited = Array.from({length: M}, () => Array(N).fill(false));
    let maxRegion = 0; // 记录最大连通区域的大小
    // 定义四个方向的移动:上、下、左、右
    const directions = [
        [-1, 0],
        [1, 0],
        [0, -1],
        [0, 1]
    ];
    // 遍历每一个网格点
    for(let i = 0; i < M; i++){
        for(let j = 0; j < N; j++){
            if(!visited[i][j]){
                // 使用BFS计算当前连通区域的大小
                let queue = [];
                queue.push([i, j]);
                visited[i][j] = true;
                let count = 1;
                while(queue.length > 0){
                    let [x, y] = queue.shift();
                    for(let dir = 0; dir < directions.length; dir++){
                        let newX = x + directions[dir][0];
                        let newY = y + directions[dir][1];
                        // 判断新位置是否在网格范围内且未被访问
                        if(newX >=0 && newX < M && newY >=0 && newY < N && !visited[newX][newY]){
                            // 判断编号差的绝对值是否小于等于1
                            if(Math.abs(grid[x][y] - grid[newX][newY]) <= 1){
                                queue.push([newX, newY]);
                                visited[newX][newY] = true;
                                count++;
                            }
                        }
                    }
                }
                // 更新最大连通区域的大小
                if(count > maxRegion){
                    maxRegion = count;
                }
            }
        }
    }
    // 输出结果
    console.log(maxRegion);
});

八、C算法源码

/* C语言版本 */
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

// 定义队列结构
typedef struct {
    int x;
    int y;
} Point;

// 定义队列大小
typedef struct {
    Point *data;
    int front;
    int rear;
    int size;
} Queue;

// 初始化队列
Queue* createQueue(int max_size){
    Queue *q = (Queue*)malloc(sizeof(Queue));
    q->data = (Point*)malloc(sizeof(Point)*max_size);
    q->front = 0;
    q->rear = 0;
    q->size = max_size;
    return q;
}

// 判断队列是否为空
bool isEmpty(Queue *q){
    return q->front == q->rear;
}

// 入队
void enqueue(Queue *q, int x, int y){
    q->data[q->rear].x = x;
    q->data[q->rear].y = y;
    q->rear = (q->rear + 1) % q->size;
}

// 出队
Point dequeue(Queue *q){
    Point p = q->data[q->front];
    q->front = (q->front + 1) % q->size;
    return p;
}

int main(){
    int M, N;
    // 读取网格的行数M和列数N
    scanf("%d %d", &M, &N);
    // 动态分配网格数组
    int **grid = (int**)malloc(sizeof(int*)*M);
    for(int i = 0; i < M; i++){
        grid[i] = (int*)malloc(sizeof(int)*N);
        for(int j = 0; j < N; j++){
            scanf("%d", &grid[i][j]);
        }
    }
    // 初始化访问标记数组,全部设置为false
    bool **visited = (bool**)malloc(sizeof(bool*)*M);
    for(int i = 0; i < M; i++){
        visited[i] = (bool*)malloc(sizeof(bool)*N);
        for(int j = 0; j < N; j++){
            visited[i][j] = false;
        }
    }
    int max_region = 0; // 记录最大连通区域的大小
    // 定义四个方向的移动:上、下、左、右
    int dx[4] = {-1, 1, 0, 0};
    int dy[4] = {0, 0, -1, 1};
    // 创建队列,最大可能大小为M*N
    Queue *q = createQueue(M*N);
    // 遍历每一个网格点
    for(int i = 0; i < M; i++){
        for(int j = 0; j < N; j++){
            if(!visited[i][j]){
                // 使用BFS计算当前连通区域的大小
                enqueue(q, i, j);
                visited[i][j] = true;
                int count = 1;
                while(!isEmpty(q)){
                    Point p = dequeue(q);
                    int x = p.x;
                    int y = p.y;
                    for(int dir = 0; dir < 4; dir++){
                        int new_x = x + dx[dir];
                        int new_y = y + dy[dir];
                        // 判断新位置是否在网格范围内且未被访问
                        if(new_x >=0 && new_x < M && new_y >=0 && new_y < N && !visited[new_x][new_y]){
                            // 判断编号差的绝对值是否小于等于1
                            if(abs(grid[x][y] - grid[new_x][new_y]) <= 1){
                                enqueue(q, new_x, new_y);
                                visited[new_x][new_y] = true;
                                count++;
                            }
                        }
                    }
                }
                // 更新最大连通区域的大小
                if(count > max_region){
                    max_region = count;
                }
            }
        }
    }
    // 输出结果
    printf("%d\n", max_region);
    // 释放内存
    for(int i = 0; i < M; i++) {
        free(grid[i]);
        free(visited[i]);
    }
    free(grid);
    free(visited);
    free(q->data);
    free(q);
    return 0;
}

九、C++算法源码

// C++版本
#include <bits/stdc++.h>
using namespace std;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int M, N;
    // 读取网格的行数M和列数N
    cin >> M >> N;
    // 初始化网格数组
    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];
        }
    }
    // 初始化访问标记数组,全部设置为false
    vector<vector<bool>> visited(M, vector<bool>(N, false));
    int max_region = 0; // 记录最大连通区域的大小
    // 定义四个方向的移动:上、下、左、右
    int dx[4] = {-1, 1, 0, 0};
    int dy[4] = {0, 0, -1, 1};
    // 遍历每一个网格点
    for(int i = 0; i < M; i++){
        for(int j = 0; j < N; j++){
            if(!visited[i][j]){
                // 使用BFS计算当前连通区域的大小
                queue<pair<int, int>> q;
                q.push({i, j});
                visited[i][j] = true;
                int count = 1;
                while(!q.empty()){
                    pair<int, int> p = q.front();
                    q.pop();
                    int x = p.first;
                    int y = p.second;
                    for(int dir = 0; dir < 4; dir++){
                        int new_x = x + dx[dir];
                        int new_y = y + dy[dir];
                        // 判断新位置是否在网格范围内且未被访问
                        if(new_x >=0 && new_x < M && new_y >=0 && new_y < N && !visited[new_x][new_y]){
                            // 判断编号差的绝对值是否小于等于1
                            if(abs(grid[x][y] - grid[new_x][new_y]) <= 1){
                                q.push({new_x, new_y});
                                visited[new_x][new_y] = true;
                                count++;
                            }
                        }
                    }
                }
                // 更新最大连通区域的大小
                if(count > max_region){
                    max_region = count;
                }
            }
        }
    }
    // 输出结果
    cout << max_region;
    return 0;
}


🏆下一篇:华为OD机试真题 - 简易内存池(Python/JS/C/C++ 2024 E卷 200分)

🏆本文收录于,华为OD机试真题(Python/JS/C/C++)

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。

在这里插入图片描述

华为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、付费专栏及课程。

余额充值