2025 A卷 200分 题型
本文涵盖详细的问题分析、解题思路、代码实现、代码详解、测试用例以及综合分析;
并提供Java、python、JavaScript、C++、C语言、GO六种语言的最佳实现方式!
本文收录于专栏:《2025华为OD真题目录+全流程解析/备考攻略/经验分享》
华为OD机试真题《宜居星球改造计划》:
目录
- 题目名称:宜居星球改造计划
- 题目描述
- Java
- 问题分析
- 解题思路
- 代码实现
- 代码详细解析
- 示例测试
- 综合分析
- python
- 问题分析
- 解题思路
- 代码实现
- 代码详细解析
- 示例测试
- 综合分析
- JavaScript
- 问题分析
- 解题思路
- 代码实现
- 代码详细解析
- 示例测试
- 综合分析
- C++
- 问题分析
- 解题思路
- 代码实现
- 代码详细解析
- 示例测试
- 综合分析
- C语言
- 问题分析
- 解题思路
- 代码实现
- 代码详细解析
- 示例测试
- 综合分析
- GO
- 问题分析
- 解题思路
- 代码实现
- 代码详细解析
- 示例测试
- 综合分析
题目名称:宜居星球改造计划
知识点:字符串、广度优先搜索(BFS)、逻辑处理
时间限制:1秒
空间限制:256MB
语言限制:不限
题目描述
2XXX年,人类通过火星大气改造分析,使其具备理论上的宜居条件。由于技术限制,改造需以局部网格进行。待改造区域为 row * column 网格,每个网格的值为:
- YES:已完成大气改造的宜居区。
- NO:未改造但可改造的区域。
- NA:死亡区,不可改造且无法穿过。
规则说明
- 初始状态可能存在多个宜居区(YES),每个太阳日单位,宜居区会向上下左右四个方向扩散,将相邻的NO区域自动改造为YES。
- 要求计算所有NO区域是否能在有限时间内全部变为YES。若可以,返回改造所需的最短太阳日天数;否则返回 -1。
- 注意:若初始网格中无YES或存在无法被扩散的NO区域(如被NA包围),则返回-1。
输入描述
- 输入为 row * column 的网格数据,每行用空格分隔,例如:
YES YES NO NO NO NO NA NO YES
输出描述
- 返回改造完成的最小太阳日天数,若无法完成则返回 -1。
示例
输入1
YES YES NO
NO NO NO
YES NO NO
输出1
2
说明:经过2个太阳日,所有NO被改造为YES。
输入2
YES NO NO NO
NO NO NO NO
NO NO NO NO
NO NO NO NO
输出2
6
输入3
NO NA
输出3
-1
说明:无初始YES,无法开始改造。
输入4
YES NO NO YES
NO NO YES NO
NO YES NA NA
YES NO NA NO
输出4
-1
说明:右下角NO被NA包围,无法被扩散。
Java
问题分析
我们需要计算在给定网格中所有NO区域是否可以被初始的YES区域通过四向扩散完全覆盖,并求出所需的最小天数。若存在无法覆盖的NO区域或没有初始YES区域,则返回-1。
解题思路
- 输入处理与初始化:读取网格数据,统计初始YES位置和NO总数。
- 多源BFS:以所有初始YES为起点进行广度优先搜索,逐层扩散。
- 时间计算:每完成一层扩散(即一天),检查是否所有NO已被覆盖。
- 结果验证:若扩散结束后仍有未覆盖的NO,返回-1。
代码实现
import java.util.*;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);List<String[]> gridLines = new ArrayList<>();// 读取输入构建网格while (scanner.hasNextLine()) {String line = scanner.nextLine().trim();if (line.isEmpty()) continue;gridLines.add(line.split("\\s+"));}if (gridLines.isEmpty()) {System.out.println(-1);return;}int rows = gridLines.size();int cols = gridLines.get(0).length;String[][] grid = new String[rows][cols];Queue<int[]> queue = new LinkedList<>();int remainingNO = 0;// 初始化队列和统计NO数量for (int i = 0; i < rows; i++) {for (int j = 0; j < cols; j++) {grid[i][j] = gridLines.get(i)[j];if (grid[i][j].equals("YES")) {queue.add(new int[]{i, j});} else if (grid[i][j].equals("NO")) {remainingNO++;}}}// 无初始YES或全为YESif (queue.isEmpty()) {System.out.println(-1);return;}if (remainingNO == 0) {System.out.println(0);return;}int[][] dirs = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};int days = 0;// BFS处理扩散while (!queue.isEmpty()) {int size = queue.size();boolean hasSpread = false;for (int i = 0; i < size; i++) {int[] pos = queue.poll();for (int[] dir : dirs) {int x = pos[0] + dir[0];int y = pos[1] + dir[1];if (x >= 0 && x < rows && y >= 0 && y < cols && grid[x][y].equals("NO")) {grid[x][y] = "YES";queue.add(new int[]{x, y});remainingNO--;hasSpread = true;}}}if (hasSpread) days++;if (remainingNO == 0) {System.out.println(days);return;}}System.out.println(-1);}
}
代码详细解析
- 输入处理:读取输入行并分割成网格数组。
- 网格初始化:遍历网格,记录初始YES位置到队列,并统计NO总数。
- 边界条件处理:
- 无初始YES直接返回-1。
- 没有NO时返回0天。
- BFS扩散:
- 使用队列进行层次遍历,每次处理一层节点。
- 对每个节点,检查四向邻居是否为NO,若是则标记为YES并加入队列。
- 若该层有扩散行为(
hasSpread
),天数加一。
- 结果判断:若所有NO被覆盖,返回天数;否则返回-1。
示例测试
示例1输入:
YES YES NO
NO NO NO
YES NO NO
输出:
2
解析:
- 第1天扩散到周围NO,第2天完成剩余扩散。
示例2输入:
NO NA
输出:
-1
解析:
- 无初始YES,无法开始扩散。
示例3输入:
YES NO NO YES
NO NO YES NO
NO YES NA NA
YES NO NA NO
输出:
-1
解析:
- 右下角NO被NA包围,无法扩散。
综合分析
- 时间复杂度:O(N×M),每个网格节点被访问一次。
- 空间复杂度:O(N×M),用于存储网格和队列。
- 优势:
- 多源BFS高效:同时处理多个起点,确保最短路径。
- 实时剪枝:一旦所有NO覆盖立即返回,减少无效计算。
- 适用场景:网格规模中等,且扩散路径无复杂障碍时表现最佳。
python
问题分析
我们需要计算在给定网格中所有NO区域是否可以被初始的YES区域通过四向扩散完全覆盖,并求出所需的最短天数。若存在无法覆盖的NO区域或没有初始YES区域,则返回-1。
解题思路
- 输入处理:读取网格数据,统计初始YES位置和NO总数。
- 多源BFS:以所有初始YES为起点进行广度优先搜索,按层扩散。
- 时间计算:每完成一层扩散(即一天),检查是否所有NO已被覆盖。
- 结果验证:若扩散结束后仍有未覆盖的NO,返回-1。
代码实现
import sys
from collections import dequedef main():# 读取输入构建网格grid = []for line in sys.stdin:line = line.strip()if not line:continuegrid.append