华为OD机试真题——欢乐周末 (2025B卷:200分)Java/python/JavaScript/C/C++/GO最佳实现
2025 B卷 200分 题型
本专栏内全部题目均提供Java、python、JavaScript、C、C++、GO六种语言的最佳实现方式;
并且每种语言均涵盖详细的问题分析、解题思路、代码实现、代码详解、3个测试用例以及综合分析;
本文收录于专栏:《2025华为OD真题目录+全流程解析+备考攻略+经验分享》
华为OD机试真题《欢乐周末》:
文章快捷目录
题目描述及说明
Java
python
JavaScript
C++
C
GO
题目名称:欢乐周末
- 知识点:深度优先搜索(DFS)或广度优先搜索(BFS)、连通性分析。
- 时间限制:1秒。
- 空间限制:256MB。
- 限定语言:不限。
注:实际考试中,需注意输入输出的格式要求及边界条件(如障碍物包围或无可行路径的情况)。
题目描述
小华和小为是很要好的朋友,他们约定周末一起吃饭。通过手机交流,他们在地图上选择了多个聚餐地点(由于自然地形等原因,部分聚餐地点不可达)。求小华和小为都能到达的聚餐地点有多少个?
输入描述
- 第一行输入两个整数
m
和n
,分别代表地图的长度和宽度(4 ≤ m, n ≤ 100)。 - 接下来
m
行,每行输入n
个数字,表示地图的具体信息:0
:通畅的道路1
:障碍物(且仅1
为障碍物)2
:小华或小为的位置(地图中必定有且仅有2个)3
:被选中的聚餐地点(非障碍物,数量k
满足 1 < k ≤ 100)。
输出描述
- 输出一个整数,表示小华和小为都能到达的聚餐地点数量,行末无空格。
示例
输入:
4 4
2 1 0 3
0 1 2 1
0 3 0 0
0 0 0 0
输出:
2
说明:地图中有两个聚餐地点(3
),两人均可到达,故输出 2
。
Java
问题分析
题目要求找到小华和小为都能到达的聚餐地点数量。关键在于分别找出两人能到达的所有聚餐点,然后求交集的大小。
解题思路
- 输入处理:读取地图并定位两人的起始位置。
- 连通性分析:对每个起点执行 BFS,找到所有可达的聚餐点(标记为 3)。
- 求交集:统计两人可达的 3 的重叠数量。
代码实现
import java.util.*;public class HappyWeekend {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);// 读取地图尺寸int m = scanner.nextInt();int n = scanner.nextInt();int[][] map = new int[m][n];List<int[]> starts = new ArrayList<>(); // 存储两个起始点// 读取地图数据并记录起始点for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {map[i][j] = scanner.nextInt();if (map[i][j] == 2) { // 发现起始点starts.add(new int[]{i, j});}}}scanner.close();// 分别获取两人的可达聚餐点Set<String> reachable1 = bfs(map, starts.get(0), m, n);Set<String> reachable2 = bfs(map, starts.get(1), m, n);// 计算交集数量int count = 0;for (String pos : reachable1) {if (reachable2.contains(pos)) {count++;}}System.out.println(count);}// BFS遍历获取所有可达的3的位置private static Set<String> bfs(int[][] map, int[] start, int m, int n) {Set<String> reachable = new HashSet<>(); // 存储可达的3的坐标boolean[][] visited = new boolean[m][n]; // 访问标记数组Queue<int[]> queue = new LinkedList<>(); // BFS队列// 初始化队列和访问数组queue.offer(start);visited[start[0]][start[1]] = true;int[][] directions = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; // 四个移动方向while (!queue.isEmpty()) {int[] current = queue.poll();int x = current[0], y = current[0];// 如果当前点是聚餐点,记录坐标if (map[x][y] == 3) {reachable.add(x + "," + y);}// 遍历四个方向for (int[] dir : directions) {int nx = x + dir[0];int ny = y + dir[1];// 检查新坐标是否合法且未被访问过,并且不是障碍物if (nx >= 0 && nx < m && ny >= 0 && ny < n && !visited[nx][ny] && map[nx][ny] != 1) {visited[nx][ny] = true;queue.offer(new int[]{nx, ny});}}}return reachable;}
}
代码解析
- 输入读取:读取地图尺寸和地图数据,同时记录两个起始坐标。
- BFS函数:
reachable
集合存储可达的3的坐标。visited
数组标记已访问的位置,避免重复处理。queue
实现 BFS 的遍历逻辑。- 每次取出队列头部节点,检查是否是3,并加入集合。
- 方向遍历:对上下左右四个方向检查是否越界、是否可通行。
- 求交集:遍历第一个集合,检查是否在第二个集合中存在。
示例测试
示例1:
输入:
4 4
2 1 0 3
0 1 2 1
0 3 0 0
0 0 0 0
输出:2
示例2:
输入:
3 3
2 0 3
0 1 3
3 0 2
输出:1
(假设两人共同可达一个3)
示例3:
输入:
5 5
2 0 0 0 0
0 1 1 1 0
0 1 3 1 0
0 1 1 1 0
0 0 0 0 2
输出:0
(所有3都被障碍物包围)
综合分析
最优性分析:
- 时间复杂度:O(m×n)。每个 BFS 最多访问每个节点一次。
- 空间复杂度:O(m×n)。存储访问标记和队列。
正确性保证:
- BFS 确保所有可达点都被访问到。
- 精确处理边界条件和移动方向。
应用场景:
- 地图导航中的连通区域分析。
- 游戏中的路径可达性判断。
- 社交网络中的关系链分析。
python
问题分析
题目要求找出小华和小为都能到达的聚餐地点数量。每个聚餐地点必须是两人都能到达的,故需分别遍历两人的可达路径,然后取交集。
解题思路
- 输入处理:读取地图并记录两个起点位置。
- BFS遍历:对每个起点执行广度优先搜索,记录所有可达的
3
的位置。 - 求交集:统计两人可达的
3
的重叠数量。
代码实现
from collections import deque