目录
- 一、题目描述
- 二、输入描述
- 三、输出描述
- 四、深度优先搜索dfs
- 五、解题思路
- 六、Java算法源码
- 七、效果展示
- 1、输入
- 2、输出
- 3、说明
- 4、如果增加目标敌人数量K为5
- 5、来,上强度
华为OD机试 2023B卷题库疯狂收录中,刷题点这里
一、题目描述
有一个大小是N*M的战场地图,被枪毙 ‘#’ 分隔成大小不同的区域,上下左右四个方向相邻的空地’.',属于同一个区域,只有空地上可能存在敌人 ‘E’ ,请求出地图上总共有多少区域里的敌人数小于K。
二、输入描述
第一行输入为N,M,K;
- N表示地图的行数;
- M表示地图的列数;
- K表示目标敌人数量;
取值范围:
N <= 100 、 M <= 100
第二行开始为N * M大小的字符数组。
三、输出描述
敌人数小于K的区域数量。
四、深度优先搜索dfs
在我们遇到的一些问题当中,有些问题我们不能够确切的找出数学模型,即找不出一种直接求解的方法,解决这一类问题,我们一般采用搜索的方法解决。搜索就是用问题的所有可能去试探,按照一定的顺序、规则,不断去试探,直到找到问题的解,试完了也没有找到解,那就是无解,试探时一定要试探完所有的情况(实际上就是穷举);
对于问题的第一个状态,叫初始状态,要求的状态叫目标状态。
搜索就是把规则应用于实始状态,在其产生的状态中,直到得到一个目标状态为止。
产生新的状态的过程叫扩展(由一个状态,应用规则,产生新状态的过程)。
搜索的要点:
- 初始状态;
- 重复产生新状态;
- 检查新状态是否为目标,是结束,否转(2);
如果搜索是以接近起始状态的程序依次扩展状态的,叫宽度优先搜索。
如果扩展是首先扩展新产生的状态,则叫深度优先搜索。
深度优先搜索用一个数组存放产生的所有状态。
- 把初始状态放入数组中,设为当前状态;
- 扩展当前的状态,产生一个新的状态放入数组中,同时把新产生的状态设为当前状态;
- 判断当前状态是否和前面的重复,如果重复则回到上一个状态,产生它的另一状态;
- 判断当前状态是否为目标状态,如果是目标,则找到一个解答,结束算法;
- 如果数组为空,说明无解。
五、解题思路
- 第一行输入三个数,分别是:地图的行数N、地图的列数M、目标敌人数量K;
- 通过Java8 Steam分隔初始化N、M、K;
- 定义一个二维数组visitedMatrix,记录是否被访问过;
- 定义二维矩阵matrix,存储N * M大小的字符数组;
- 定义变量areaSum,存储敌人数小于K的区域数量;
- 利用深度优先搜索dfs算法,获取敌人数小于K的区域数量;
- 输出敌人数小于K的区域数量。
六、Java算法源码
package com.guor.od;import java.util.Scanner;
import java.util.*;public class OdTest {public static boolean[][] visitedMatrix;public static int[][] directions = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};public static void main(String[] args) {Scanner in = new Scanner(System.in);int[] arr = Arrays.stream(in.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();// 地图的行数int N = arr[0];// 地图的列数int M = arr[1];// 目标敌人数量int K = arr[2];// 矩阵某值是否被访问过visitedMatrix = new boolean[N][M];// 定义二维矩阵,存储N * M大小的字符数组char[][] matrix = new char[N][];for (int i = 0; i < N; i++) {matrix[i] = in.nextLine().toCharArray();}// 敌人数小于K的区域数量int areaSum = 0;for (int i = 0; i < N; i++) {for (int j = 0; j < M; j++) {if (visitedMatrix[i][j] || matrix[i][j] == '#') {continue;}// 利用深度优先搜索dfs算法,获取敌人数小于K的区域数量areaSum += dfs(i, j, matrix, N, M) < K ? 1 : 0;}}// 输出敌人数小于K的区域数量System.out.println(areaSum);}/*** 利用深度优先搜索dfs算法,获取敌人数小于K的区域数量** @param i 地图的行数,由0开始的变量* @param j 地图的列数,由0开始的变量* @param matrix 二维矩阵,N * M大小的字符数组* @param N 矩阵的总行数* @param M 矩阵的总列数* @return*/public static int dfs(int i, int j, char[][] matrix, int N, int M) {// 敌军数量int enemy_count = 0;// 访问过visitedMatrix[i][j] = true;// 存在敌人 ‘E’,敌军数量+1if (matrix[i][j] == 'E') {enemy_count += 1;}// 栈中保存敌军的位置列表LinkedList<int[]> stack = new LinkedList<>();stack.add(new int[]{i, j});while (stack.size() > 0) {int[] pos = stack.removeLast();int x = pos[0], y = pos[1];// 上下左右四个方向for (int k = 0; k < 4; k++) {int new_x = x + directions[k][0];int new_y = y + directions[k][1];if (new_x >= 0 && new_x < N && new_y >= 0 && new_y < M && !visitedMatrix[new_x][new_y] && matrix[new_x][new_y] != '#') {// 访问过visitedMatrix[new_x][new_y] = true;// 存在敌人 ‘E’,敌军数量+1if (matrix[new_x][new_y] == 'E') {enemy_count += 1;}stack.add(new int[]{new_x, new_y});}}}// 敌人数小于K的区域数量return enemy_count;}
}
七、效果展示
1、输入
4 6 3
…#EE.
E.#E…
#E#.E.
#.#…
2、输出
1
3、说明
地图被墙壁分为两个区域,左边区域有2个敌人,右边区域有4个敌人,符合条件的区域数量是1。
4、如果增加目标敌人数量K为5
地图被墙壁分为两个区域,左边区域有2个敌人,右边区域有4个敌人,符合条件的区域数量是2。
5、来,上强度
6 8 4
…#EE.#E
E.#E…#.
#E#.E.#.
#.#…#E
#.#.E.#E
#.#…#.
我草,不至于吧,哪吒,这眼花缭乱的,你这是“战场索鬼”吧?
好吧,上截图。
- 如上图所示,战场被枪毙 ‘#’ 分隔成大小不同的区域
- 第一个区域2个敌人;
- 第二个区域5个敌人;
- 第三个区域3个敌人。
- 目标敌人数量是4;
- 敌人数小于K的区域数量为2;
🏆下一篇:华为OD机试真题 Java 实现【简易内存池】【2023 B卷 200分 考生抽中题】
🏆本文收录于,华为OD机试(JAVA)真题(A卷+B卷)
刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试,发现新题目,随时更新,全天CSDN在线答疑。