华为OD机试 2023B卷题库疯狂收录中,刷题点这里
有一个大小是N*M的战场地图,被枪毙 ‘#’ 分隔成大小不同的区域,上下左右四个方向相邻的空地’.',属于同一个区域,只有空地上可能存在敌人 ‘E’ ,请求出地图上总共有多少区域里的敌人数小于K。
第一行输入为N,M,K;
取值范围:
N <= 100 、 M <= 100
第二行开始为N * M大小的字符数组。
敌人数小于K的区域数量。
在我们遇到的一些问题当中,有些问题我们不能够确切的找出数学模型,即找不出一种直接求解的方法,解决这一类问题,我们一般采用搜索的方法解决。搜索就是用问题的所有可能去试探,按照一定的顺序、规则,不断去试探,直到找到问题的解,试完了也没有找到解,那就是无解,试探时一定要试探完所有的情况(实际上就是穷举);
对于问题的第一个状态,叫初始状态,要求的状态叫目标状态。
搜索就是把规则应用于实始状态,在其产生的状态中,直到得到一个目标状态为止。
产生新的状态的过程叫扩展(由一个状态,应用规则,产生新状态的过程)。
搜索的要点:
如果搜索是以接近起始状态的程序依次扩展状态的,叫宽度优先搜索。
如果扩展是首先扩展新产生的状态,则叫深度优先搜索。
深度优先搜索用一个数组存放产生的所有状态。
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’,敌军数量+1
if (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’,敌军数量+1
if (matrix[new_x][new_y] == 'E') {
enemy_count += 1;
}
stack.add(new int[]{new_x, new_y});
}
}
}
// 敌人数小于K的区域数量
return enemy_count;
}
}
4 6 3
…#EE.
E.#E…
#E#.E.
#.#…
1
地图被墙壁分为两个区域,左边区域有2个敌人,右边区域有4个敌人,符合条件的区域数量是1。
地图被墙壁分为两个区域,左边区域有2个敌人,右边区域有4个敌人,符合条件的区域数量是2。
6 8 4
…#EE.#E
E.#E…#.
#E#.E.#.
#.#…#E
#.#.E.#E
#.#…#.
我草,不至于吧,哪吒,这眼花缭乱的,你这是“战场索鬼”吧?
好吧,上截图。
下一篇:华为OD机试真题 Java 实现【简易内存池】【2023 B卷 200分 考生抽中题】
本文收录于,华为OD机试(JAVA)真题(A卷+B卷)
刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试,发现新题目,随时更新,全天CSDN在线答疑。