【限时免费】20天拿下华为OD笔试【DFS/BFS】2023B-战场索敌【欧弟算法】全网注释最详细分类最全的华为OD真题题解

文章目录

  • 题目描述与示例
    • 题目描述
    • 输入描述
    • 输出描述
    • 示例
      • 输入
      • 输出
  • 解题思路
  • 代码
    • 解法一:BFS
      • python
      • java
      • cpp
    • 解法二:DFS
      • python
      • java
      • cpp
    • 时空复杂度
  • 华为OD算法/大厂面试高频题算法练习冲刺训练

题目描述与示例

题目描述

有一个大小是N`` ``*`` ``M的战场地图,被墙壁'#' 分隔成大小不同的区域,上下左右四个方向相邻的空地 '.',属于同一个区域,只有空地上可能存在敌人'E',请求出地图上总共有多少区域里的敌人数小于K

输入描述

第一行输入为N`` ``M`` ``K; N表示地图的行数,M表示地图的列数,K表示目标敌人数量 N``, ``M`` ``<=`` ``100 之后为一个N`` ``x`` ``M大小的字符数组

输出描述

敌人数小于K的区域数量

示例

输入

3 5 2
..#EE
E.#E.
###..

输出

1

解题思路

本题也是属于岛屿类型DFS/BFS的模板题,对二维网格直接进行搜索即可。

代码

解法一:BFS

python

# 题目:2023B-战场索敌
# 分值:200
# 作者:闭着眼睛学数理化
# 算法:BFS
# 代码看不懂的地方,请直接在群上提问

from collections import deque

# 表示四个方向的数组
DIRECTIONS = [(0,1), (1,0), (-1,0), (0,-1)]

# 输入行数n,列数m,阈值k
n, m, k = map(int, input().split())
# 输入网格
grid = list()
for _ in range(n):
    grid.append(input())


# 答案变量,用于记录敌人个数大于k的的连通块的个数
ans = 0
# 用于检查的二维矩阵
# 0表示没检查过,1表示检查过了
check_list = [[0] * m for _ in range(n)]

# 最外层的大的双重循环,是用来找BFS的起始搜索位置的
for i in range(n):
    for j in range(m):
        # 找到一个"."或"E",并且这个"."或"E"从未被搜索过:那么可以进行BFS的搜索
        if grid[i][j] != "#" and check_list[i][j] == 0:
            # BFS的过程
            q = deque()
            q.append([i, j])        # BFS的起始点
            check_list[i][j] = 1
            # 初始化当前连通块的敌人数目cur_num为0
            cur_num = 0
            while len(q) > 0:       # 当队列中还有元素时,持续地进行搜索
                qSize = len(q)
                for _ in range(qSize):
                    # 弹出队头元素,为当前点
                    x, y = q.popleft()
                    # 如果当前位置是敌人,则更新当前连通块的敌人数目cur_num
                    if grid[x][y] == "E":
                        cur_num += 1
                    for dx, dy in DIRECTIONS:
                        nxt_x, nxt_y = x+dx, y+dy
                        # 若下一个点要加入队列,应该满足以下三个条件:
                        # 1.没有越界
                        # 2.在grid中值为"."或"E"
                        # 3.尚未被检查过
                        if 0 <= nxt_x < n and 0 <= nxt_y < m:       # 越界判断
                            if grid[nxt_x][nxt_y] != "#" and check_list[nxt_x][nxt_y] == 0:
                                q.append([nxt_x, nxt_y])        # 入队
                                check_list[nxt_x][nxt_y] = 1    # 标记为已检查过

            # BFS搜索完成,如果cur_num小于k,更新ans
            if cur_num < k:
                ans += 1

print(ans)

java

import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

public class Main {
    // Represent four directions as an array
    private static final int[][] DIRECTIONS = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}};

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        // Input the number of rows n, columns m, and the threshold k
        int n = scanner.nextInt();
        int m = scanner.nextInt();
        int k = scanner.nextInt();

        // Input the grid
        char[][] grid = new char[n][m];
        for (int i = 0; i < n; i++) {
            grid[i] = scanner.next().toCharArray();
        }

        // Answer variable to count the number of connected blocks with more than k enemies
        int ans = 0;

        // Two-dimensional matrix for checking
        // 0 means not checked, 1 means checked
        int[][] checkList = new int[n][m];

        // Outermost double loop is used to find BFS's starting search position
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                // Find a "." or "E" and it has not been searched before: then BFS search can be performed
                if (grid[i][j] != '#' && checkList[i][j] == 0) {
                    // BFS process
                    Queue<int[]> queue = new LinkedList<>();
                    queue.add(new int[]{i, j}); // BFS starting point
                    checkList[i][j] = 1;
                    // Initialize the number of enemies in the current connected block curNum to 0
                    int curNum = 0;
                    while (!queue.isEmpty()) { // Continue searching as long as there are elements in the queue
                        int qSize = queue.size();
                        for (int q = 0; q < qSize; q++) {
                            // Dequeue the front element as the current point
                            int[] current = queue.poll();
                            int x = current[0];
                            int y = current[1];
                            // If the current position is an enemy, update curNum
                            if (grid[x][y] == 'E') {
                                curNum++;
                            }
                            for (int[] direction : DIRECTIONS) {
                                int nextX = x + direction[0];
                                int nextY = y + direction[1];
                                // If the next point can be added to the queue, it should satisfy three conditions:
                                // 1. Not out of bounds
                                // 2. The value in the grid is "." or "E"
                                // 3. Has not been checked yet
                                if (0 <= nextX && nextX < n && 0 <= nextY && nextY < m &&
                                        (grid[nextX][nextY] != '#' && checkList[nextX][nextY] == 0)) {
                                    // Enqueue the next point
                                    queue.add(new int[]{nextX, nextY});
                                    // Mark it as checked
                                    checkList[nextX][nextY] = 1;
                                }
                            }
                        }
                    }
                    // BFS search is complete, if curNum is less than k, update ans
                    if (curNum < k) {
                        ans++;
                    }
                }
            }
        }

        System.out.println(ans);
    }
}

cpp

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

using namespace std;

// Represent four directions as a vector of pairs
const vector<pair<int, int>> DIRECTIONS = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}};

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

    // Input the grid
    vector<string> grid(n);
    for (int i = 0; i < n; i++) {
        cin >> grid[i];
    }

    // Answer variable to count the number of connected blocks with more than k enemies
    int ans = 0;

    // Two-dimensional matrix for checking
    // 0 means not checked, 1 means checked
    vector<vector<int>> checkList(n, vector<int>(m, 0));

    // Outermost double loop is used to find BFS's starting search position
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            // Find a "." or "E" and it has not been searched before: then BFS search can be performed
            if (grid[i][j] != '#' && checkList[i][j] == 0) {
                // BFS process
                queue<pair<int, int>> q;
                q.push({i, j}); // BFS starting point
                checkList[i][j] = 1;
                // Initialize the number of enemies in the current connected block curNum to 0
                int curNum = 0;
                while (!q.empty()) { // Continue searching as long as there are elements in the queue
                    pair<int, int> current = q.front(); // Dequeue the front element as the current point
                    q.pop();
                    int x = current.first;
                    int y = current.second;
                    // If the current position is an enemy, update curNum
                    if (grid[x][y] == 'E') {
                        curNum++;
                    }
                    for (const auto& direction : DIRECTIONS) {
                        int nextX = x + direction.first;
                        int nextY = y + direction.second;
                        // If the next point can be added to the queue, it should satisfy three conditions:
                        // 1. Not out of bounds
                        // 2. The value in the grid is "." or "E"
                        // 3. Has not been checked yet
                        if (0 <= nextX && nextX < n && 0 <= nextY && nextY < m &&
                            (grid[nextX][nextY] != '#' && checkList[nextX][nextY] == 0)) {
                            // Enqueue the next point
                            q.push({nextX, nextY});
                            // Mark it as checked
                            checkList[nextX][nextY] = 1;
                        }
                    }
                }
                // BFS search is complete, if curNum is less than k, update ans
                if (curNum < k) {
                    ans++;
                }
            }
        }
    }

    cout << ans << endl;
    return 0;
}

解法二:DFS

python

# 题目:2023B-战场索敌
# 分值:200
# 作者:闭着眼睛学数理化
# 算法:DFS
# 代码看不懂的地方,请直接在群上提问


# 表示四个方向的数组
DIRECTIONS = [(0,1), (1,0), (-1,0), (0,-1)]


# 输入行数n,列数m,阈值k
n, m, k = map(int, input().split())
# 输入网格
grid = list()
for _ in range(n):
    grid.append(input())


# 答案变量,用于记录敌人个数大于k的的连通块的个数
ans = 0
# 用于检查的二维矩阵
# 0表示没检查过,1表示检查过了
check_list = [[0] * m for _ in range(n)]

# 构建DFS递归函数
def dfs(check_list, x, y):
    # 声明变量cur_num为全局变量,表示当前DFS过程中,连通块中敌人的个数
    global cur_num
    # 将点(x, y)标记为已检查过
    check_list[x][y] = 1
    # 如果当前位置是敌人,则更新当前连通块的敌人数目cur_num
    if grid[x][y] == "E":
        cur_num += 1
    for dx, dy in DIRECTIONS:
        nxt_x, nxt_y = x + dx, y + dy
        # 若下一个点继续进行dfs,应该满足以下三个条件:
        # 1.没有越界
        # 2.在grid中值为"."或"E"
        # 3.尚未被检查过
        if 0 <= nxt_x < n and 0 <= nxt_y < m:
            if grid[nxt_x][nxt_y] != "#" and check_list[nxt_x][nxt_y] == 0:
                # 可以进行dfs
                dfs(check_list, nxt_x, nxt_y)


# 最外层的大的双重循环,是用来找DFS的起始搜索位置的
for i in range(n):
    for j in range(m):
        # 找到一个"."或"E",并且这个"."或"E"从未被搜索过:那么可以进行DFS的搜索
        if grid[i][j] != "#" and check_list[i][j] == 0:
            # 初始化当前连通块的敌人数目cur_num为0
            cur_num = 0
            dfs(check_list, i, j)
            # DFS搜索完成,如果cur_num小于k,更新ans
            if cur_num < k:
                ans += 1
                
print(ans)

java

import java.util.*;

public class Main {
    static final int[][] DIRECTIONS = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}};
    static int ans = 0;
    static char[][] grid;
    static int[][] checkList;

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

        grid = new char[n][m];
        checkList = new int[n][m];

        for (int i = 0; i < n; i++) {
            String row = scanner.next();
            for (int j = 0; j < m; j++) {
                grid[i][j] = row.charAt(j);
            }
        }

        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (grid[i][j] != '#' && checkList[i][j] == 0) {
                    int[] curNum = new int[]{0};
                    dfs(i, j, curNum);
                    if (curNum[0] < k) {
                        ans++;
                    }
                }
            }
        }

        System.out.println(ans);
    }

    static void dfs(int x, int y, int[] curNum) {
        checkList[x][y] = 1;

        if (grid[x][y] == 'E') {
            curNum[0]++;
        }

        for (int[] direction : DIRECTIONS) {
            int nextX = x + direction[0];
            int nextY = y + direction[1];

            if (nextX >= 0 && nextX < grid.length && nextY >= 0 && nextY < grid[0].length &&
                    grid[nextX][nextY] != '#' && checkList[nextX][nextY] == 0) {
                dfs(nextX, nextY, curNum);
            }
        }
    }
}

cpp

#include <iostream>
#include <vector>

using namespace std;

// Represent four directions as an array
const vector<pair<int, int>> DIRECTIONS = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}};

void dfs(vector<vector<int>>& checkList, vector<string>& grid, int x, int y, int k, int& curNum) {
    // Mark the point (x, y) as checked
    checkList[x][y] = 1;
    // If the current position is an enemy, update curNum
    if (grid[x][y] == 'E') {
        curNum++;
    }
    for (const pair<int, int>& direction : DIRECTIONS) {
        int nextX = x + direction.first;
        int nextY = y + direction.second;
        // If the next point can continue DFS, it should satisfy three conditions:
        // 1. Not out of bounds
        // 2. The value in the grid is "." or "E"
        // 3. Has not been checked yet
        if (0 <= nextX && nextX < grid.size() && 0 <= nextY && nextY < grid[0].size() &&
            (grid[nextX][nextY] != '#' && checkList[nextX][nextY] == 0)) {
            // Continue with DFS
            dfs(checkList, grid, nextX, nextY, k, curNum);
        }
    }
}

int main() {
    int n, m, k;
    cin >> n >> m >> k;
    vector<string> grid(n);

    // Input the grid
    for (int i = 0; i < n; i++) {
        cin >> grid[i];
    }

    // Answer variable to count the number of connected blocks with more than k enemies
    int ans = 0;

    // Two-dimensional matrix for checking
    // 0 means not checked, 1 means checked
    vector<vector<int>> checkList(n, vector<int>(m, 0));

    // Outermost double loop to find the starting search position for DFS
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            // Find a "." or "E" and it has not been searched before: then DFS search can be performed
            if (grid[i][j] != '#' && checkList[i][j] == 0) {
                // Initialize the number of enemies in the current connected block curNum to 0
                int curNum = 0;
                dfs(checkList, grid, i, j, k, curNum);
                // If DFS search is complete and curNum is less than k, update ans
                if (curNum < k) {
                    ans++;
                }
            }
        }
    }

    cout << ans << 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,#,DFS,算法,华为od,深度优先)