2025 A卷 200分 题型
本专栏内全部题目均提供Java、python、JavaScript、C、C++、GO六种语言的最佳实现方式;
并且每种语言均涵盖详细的问题分析、解题思路、代码实现、代码详解、3个测试用例以及综合分析;
本文收录于专栏:《2025华为OD真题目录+全流程解析+备考攻略+经验分享》
华为OD机试真题《智能驾驶》:
文章快捷目录
题目描述及说明
Java
python
JavaScript
C
GO
题目名称:智能驾驶
- 知识点:动态规划、贪心算法、图搜索(BFS/DFS)
- 时间限制:1秒
- 空间限制:256MB
- 限定语言:不限
题目描述
一辆汽车需要从 ( m \times n ) 的地图左上角(起点)行驶到右下角(终点)。每个格子有以下属性:
- -1:加油站,可加满油(油箱容量最大为100)。
- 0:障碍物,无法通过。
- 正整数:通过该格子需消耗的油量。
规则:
- 汽车可上下左右移动。
- 初始油量需确保能到达终点,计算最少初始油量。若无法到达,返回-1。
- 油箱初始为空,若起点为加油站则初始油量为100。
输入:
- 首行两个整数 ( m ) 和 ( n ),表示地图行数和列数。
- 接下来 ( m ) 行,每行 ( n ) 个整数,表示地图数据。
输出:
- 最少初始油量或-1。
示例:
输入:
2 2
10 20
30 40
输出:
70
解释:路径为右→下,初始油量需 ≥ 10(起点) + 30(下一步) = 40,但实际需覆盖路径最大累计消耗(10+20+40=70)。
Java
问题分析
汽车需要从地图左上角移动到右下角,每个格子可能有不同的油量消耗或加油站。油箱容量最大为100,初始油量为空。若起点是加油站,初始油量为100。要求找到能到达终点的最小初始油量,若无法到达返回-1。
解题思路
- 动态规划与优先队列:使用Dijkstra算法,优先扩展当前最大油量消耗最小的路径。
- 状态定义:每个状态包括当前位置、当前区段累计油量、路径最大油量消耗。
- 加油站处理:到达加油站时,油量加满,当前区段累计油量重置为0。
- 障碍物处理:遇到障碍物直接跳过。
代码实现
import java.util.*;
class State implements Comparable<State> {
int i, j;
int currentSegment;
int maxSoFar;
public State(int i, int j, int currentSegment, int maxSoFar) {
this.i = i;
this.j = j;
this.currentSegment = currentSegment;
this.maxSoFar = maxSoFar;
}
@Override
public int compareTo(State other) {
return Integer.compare(this.maxSoFar, other.maxSoFar);
}
}
public class Main {
private static String getKey(int i, int j, int segment) {
return i + "," + j + "," + segment;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int m = scanner.nextInt();
int n = scanner.nextInt();
int[][] grid = new int[m][n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
grid[i][j] = scanner.nextInt();
}
}
// 起点是障碍物
if (grid[0][0] == 0) {
System.out.println(-1);
return;
}
PriorityQueue<State> pq = new PriorityQueue<>();
Map<String, Integer> dist = new HashMap<>();
// 初始化起点
if (grid[0][0] == -1) {
pq.offer(new State(0, 0, 0, 0));
dist.put(getKey(0, 0, 0), 0);
} else {
int initialCost = grid[0][0];
pq.offer(new State(0, 0, initialCost, initialCost));
dist.put(getKey(0, 0, initialCost), initialCost);
}
int[][] dirs = {
{
0, 1}, {
1, 0}, {
0, -1}, {
-1, 0}};
while (!pq.isEmpty()) {
State state = pq.poll();
int i = state.i;
int j = state.j;
int currentSegment = state.currentSegment;
int maxSoFar = state.maxSoFar;
// 到达终点
if (i == m - 1 && j == n - 1) {
System.out.println(maxSoFar);
return;
}
String currentKey = getKey(i, j, currentSegment);
if (dist.getOrDefault(currentKey, Integer.MAX_VALUE) < maxSoFar) {
continue;
}
for (int[] dir : dirs) {
int ni = i + dir[0];
int nj = j + dir[1];
if (ni < 0 || nj < 0 || ni >= m || nj >= n) continue;
int cellValue = grid[ni][nj];
if (cellValue == 0) continue;
int cost = cellValue == -1 ? 0 : cellValue;
int newSegment = currentSegment + cost;
boolean isGasStation = cellValue == -1;
int newMax = Math.max(maxSoFar, newSegment);
// 处理加油站
if (isGasStation) {
if (newSegment > 100) continue;
newSegment = 0; // 加满油,新区段从0开始
} else {
// 来自加油站或起点是加油站,新区段不能超过100
if (currentSegment == 0 && newSegment > 100) {
continue;
}
}
int newSegmentAfter = isGasStation ? 0 : newSegment;
State newState = new State(ni, nj, newSegmentAfter, newMax);
String newKey = getKey(ni, nj, newSegmentAfter);
if (!dist.containsKey(newKey) || newMax < dist.getOrDefault(newKey, Integer.MAX_VALUE)) {
dist.put(newKey, newMax);
pq.offer(newState);
}
}
}
System.out.println(-1);
}
}
代码详解
- State类:存储当前位置、当前区段累计油量、路径最大油量消耗,并实现优先队列比较接口。
- 输入处理:读取地图数据,处理起点障碍物情况。
- 优先队列初始化:根据起点是否为加油站设置初始状态。
- 状态扩展:遍历四个方向,计算新位置的油量消耗,处理加油站逻辑,更新状态并加入优先队列。
- 终点检测:到达终点时输出结果。
示例测试
示例1输入:
2 2
10 20
30 40
输出:70
示例2输入:
3 3
-1 20 0
30 0 40
50 60 70
输出:100
(路径包含加油站,最大区段消耗为30+50=80,但需加满油)
示例3输入:
2 2
0 10
20 30
输出:-1
(起点障碍物)
综合分析
- 时间复杂度:使用优先队列处理状态,最坏情况O(N log N),适用于小规模地图。
- 空间复杂度:存储状态信息,O(MNC),C为区段油量可能值。
- 正确性:通过Dijkstra算法保证找到最优路径,处理加油站和障碍物逻辑。
- 适用性:适用于各种地图配置,正确处理油量限制和加油站逻辑。
python
问题分析
汽车需要从地图左上角移动到右下角,每个格子可能有不同的油量消耗或加油站。油箱容量最大为100,初始油量为空。若起点是加油站,初始油量为100。要求找到能到达终点的最小初始油量,若无法到达返回-1。
解题思路
- 优先队列(Dijkstra算法):每次扩展当前最大油量消耗最小的路径。
- 状态定义:每个状态包括位置、当前区段累计油量、路径最大油量消耗。
- 加油站处理:到达加油站时,油量加满,当前区段累计油量重置为0。
- 障碍物处理:遇到障碍物直接跳过。
代码实现
import heapq
def min_initial_fuel(grid):
m = len(grid)
if m == 0:
return -1
n = len(grid[0])
if grid[0][0] == 0:
return -1 # 起点是障碍物
start_val = grid[0][0]
# 初始化起点状态
if start_val == -1:
initial_segment = 0
initial_max = 0
else:
if start_val > 100:
return -1 # 初始油量不足
initial_segment = start_val
initial_max = start_val
heap = []
heapq.heappush(heap, (initial_max, 0, 0, initial_segment))
visited = {
}
visited_key = (0, 0, initial_segment)
visited[visited_key] = initial_max
dirs = [(-1, 0), (1, 0), (0, -1), (0, 1)]
while