华为OD机试真题目录点击查看: 华为OD机试2025B卷真题题库目录|机考题库 + 算法考点详解
华为OD机试2025B卷 200分题型
有一辆汽车需要从 m * n 的地图左上角(起点)开往地图的右下角(终点),去往每一个地区都需要消耗一定的油量,加油站可进行加油。
请你计算汽车确保从从起点到达终点时所需的最少初始油量。说明:
如果汽车无论如何都无法到达终点,则返回 -1
第一行为两个数字,M,N,表示地图的大小为 M N。0 < M,N ≤ 200
后面一个 M * N 的矩阵,其中的值是 0 或 -1 或正整数,加油站的总数不超过 200 个
如果汽车无论如何都无法到达终点,则返回 -1。如果汽车可以到达终点,则返回最少的初始油量
2,2
10,20
30,40
70
行走的路线为:右→下
4,4
10,30,30,20
30,30,-1,10
0,20,20,40
10,-1,30,40
70
行走的路线为:右→右→下→下→下→右
思路:二分 + BFS
二分
去枚举汽车初始油量,利用BFS
算法去判断二分确定的油是否满足车从左上角 -> 右下角。左上角 -> 右下角的行动
,因为0为障碍物。result = -1
记录可行的最小结果, 二分初始设置left = 0, right = 100 (汽车最大存储油容量)
,每次二分枚举mid = (left + right) / 2
,使用BFS
进行判断能否从左上角到右小角
right = mid - 1 , result = mid
left = mid + 1
left > right
结束。最后输出result即可。优先队列
模拟判断给定初始油量能否从左上角到达右下角。可以使用fuelLeft[][]
数组进行剪枝,fuelLeft[i][j]
剩余的最多油量进行剪枝。具体逻辑可以参照下面的代码。#include
#include
#include
#include
using namespace std;
const int MAX_FUEL = 100; // 车辆最大油量
// 判断是否能到达终点
bool canReachDestination(const vector<vector<int>>& grid, int initialFuel, int rows, int cols) {
if (grid[0][0] == 0) return false; // 起点是障碍物,无法前进
vector<vector<int>> fuelLeft(rows, vector<int>(cols, -1)); // 记录每个点的最大剩余油量
fuelLeft[0][0] = (grid[0][0] == -1) ? MAX_FUEL : initialFuel - grid[0][0];
if (fuelLeft[0][0] < 0) return false; // 初始油量不足
priority_queue<tuple<int, int, int>> pq; // 优先队列 (剩余油量, 行, 列)
pq.push({fuelLeft[0][0], 0, 0});
vector<pair<int, int>> directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; // 四个移动方向
while (!pq.empty()) {
auto [fuel, r, c] = pq.top();
pq.pop();
if (r == rows - 1 && c == cols - 1) return true; // 到达终点
for (auto& [dr, dc] : directions) {
int nr = r + dr, nc = c + dc;
if (nr >= 0 && nr < rows && nc >= 0 && nc < cols && grid[nr][nc] != 0) {
int newFuel = (grid[nr][nc] == -1) ? MAX_FUEL : fuel - grid[nr][nc];
if (newFuel > fuelLeft[nr][nc]) { // 更新更优解
fuelLeft[nr][nc] = newFuel;
pq.push({newFuel, nr, nc});
}
}
}
}
return false;
}
// 二分查找最小初始油量
int findMinimumInitialFuel(const vector<vector<int>>& grid, int rows, int cols) {
int low = 0, high = MAX_FUEL, optimalFuel = -1;
while (low <= high) {
int mid = (low + high) / 2;
if (canReachDestination(grid, mid, rows, cols)) {
optimalFuel = mid;
high = mid - 1; // 继续寻找更小油量
} else {
low = mid + 1;
}
}
return optimalFuel;
}
int main() {
int rows, cols;
// 处理逗号
char comma;
cin >> rows >> comma >> cols;
vector<vector<int>> grid(rows, vector<int>(cols));
for (int r = 0; r < rows; ++r) {
for (int c = 0; c < cols; ++c) {
if (c < cols - 1) cin >> grid[r][c] >> comma;
else cin >> grid[r][c];
}
}
cout << findMinimumInitialFuel(grid, rows, cols) << endl;
return 0;
}
import java.util.*;
public class Main {
static final int MAX_FUEL = 100; // 车辆最大油量
// 判断是否能到达终点
static boolean canReachDestination(int[][] grid, int initialFuel, int rows, int cols) {
if (grid[0][0] == 0) return false; // 起点是障碍物,无法前进
int[][] fuelLeft = new int[rows][cols]; // 记录每个点的最大剩余油量
for (int[] row : fuelLeft) Arrays.fill(row, -1);
fuelLeft[0][0] = (grid[0][0] == -1) ? MAX_FUEL : initialFuel - grid[0][0];
if (fuelLeft[0][0] < 0) return false; // 初始油量不足
PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> Integer.compare(b[0], a[0])); // 最大堆 (剩余油量, 行, 列)
pq.offer(new int[]{fuelLeft[0][0], 0, 0});
int[][] directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; // 四个移动方向
while (!pq.isEmpty()) {
int[] top = pq.poll();
int fuel = top[0], r = top[1], c = top[2];
if (r == rows - 1 && c == cols - 1) return true; // 到达终点
for (int[] dir : directions) {
int nr = r + dir[0], nc = c + dir[1];
if (nr >= 0 && nr < rows && nc >= 0 && nc < cols && grid[nr][nc] != 0) {
int newFuel = (grid[nr][nc] == -1) ? MAX_FUEL : fuel - grid[nr][nc];
if (newFuel > fuelLeft[nr][nc]) { // 更新更优解
fuelLeft[nr][nc] = newFuel;
pq.offer(new int[]{newFuel, nr, nc});
}
}
}
}
return false;
}
// 二分查找最小初始油量
static int findMinimumInitialFuel(int[][] grid, int rows, int cols) {
int low = 0, high = MAX_FUEL, optimalFuel = -1;
while (low <= high) {
int mid = (low + high) / 2;
if (canReachDestination(grid, mid, rows, cols)) {
optimalFuel = mid;
high = mid - 1; // 继续寻找更小油量
} else {
low = mid + 1;
}
}
return optimalFuel;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String[] size = scanner.nextLine().split(",");
int rows = Integer.parseInt(size[0]);
int cols = Integer.parseInt(size[1]);
int[][] grid = new int[rows][cols];
for (int r = 0; r < rows; r++) {
String[] values = scanner.nextLine().split(",");
for (int c = 0; c < cols; c++) {
grid[r][c] = Integer.parseInt(values[c]);
}
}
System.out.println(findMinimumInitialFuel(grid, rows, cols));
}
}
import sys
import heapq
MAX_FUEL = 100 # 车辆最大油量
# 判断是否能到达终点
def can_reach_destination(grid, initial_fuel, rows, cols):
if grid[0][0] == 0:
return False # 起点是障碍物,无法前进
fuel_left = [[-1] * cols for _ in range(rows)] # 记录每个点的最大剩余油量
fuel_left[0][0] = MAX_FUEL if grid[0][0] == -1 else initial_fuel - grid[0][0]
if fuel_left[0][0] < 0:
return False # 初始油量不足
pq = [(-fuel_left[0][0], 0, 0)] # 最大堆 (负剩余油量, 行, 列)
directions = [(0, 1), (1, 0), (0, -1), (-1, 0)] # 四个移动方向
while pq:
fuel, r, c = heapq.heappop(pq)
fuel = -fuel
if r == rows - 1 and c == cols - 1:
return True # 到达终点
for dr, dc in directions:
nr, nc = r + dr, c + dc
if 0 <= nr < rows and 0 <= nc < cols and grid[nr][nc] != 0:
new_fuel = MAX_FUEL if grid[nr][nc] == -1 else fuel - grid[nr][nc]
if new_fuel > fuel_left[nr][nc]:
fuel_left[nr][nc] = new_fuel
heapq.heappush(pq, (-new_fuel, nr, nc))
return False
# 二分查找最小初始油量
def find_minimum_initial_fuel(grid, rows, cols):
low, high, optimal_fuel = 0, MAX_FUEL, -1
while low <= high:
mid = (low + high) // 2
if can_reach_destination(grid, mid, rows, cols):
optimal_fuel = mid
high = mid - 1 # 继续寻找更小油量
else:
low = mid + 1
return optimal_fuel
if __name__ == "__main__":
rows, cols = map(int, sys.stdin.readline().strip().split(","))
grid = [list(map(int, sys.stdin.readline().strip().split(","))) for _ in range(rows)]
print(find_minimum_initial_fuel(grid, rows, cols))
const readline = require("readline");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
const MAX_FUEL = 100; // 车辆最大油量
// 判断是否能到达终点
function canReachDestination(grid, initialFuel, rows, cols) {
if (grid[0][0] === 0) return false;
let fuelLeft = Array.from({ length: rows }, () => Array(cols).fill(-1));
fuelLeft[0][0] = grid[0][0] === -1 ? MAX_FUEL : initialFuel - grid[0][0];
if (fuelLeft[0][0] < 0) return false;
let pq = [[fuelLeft[0][0], 0, 0]];
const directions = [[0, 1], [1, 0], [0, -1], [-1, 0]];
while (pq.length) {
pq.sort((a, b) => b[0] - a[0]);
let [fuel, r, c] = pq.shift();
if (r === rows - 1 && c === cols - 1) return true;
for (const [dr, dc] of directions) {
let nr = r + dr, nc = c + dc;
if (nr >= 0 && nr < rows && nc >= 0 && nc < cols && grid[nr][nc] !== 0) {
let newFuel = grid[nr][nc] === -1 ? MAX_FUEL : fuel - grid[nr][nc];
if (newFuel > fuelLeft[nr][nc]) {
fuelLeft[nr][nc] = newFuel;
pq.push([newFuel, nr, nc]);
}
}
}
}
return false;
}
// 二分查找最小初始油量
function findMinimumInitialFuel(grid, rows, cols) {
let low = 0, high = MAX_FUEL, optimalFuel = -1;
while (low <= high) {
let mid = Math.floor((low + high) / 2);
if (canReachDestination(grid, mid, rows, cols)) {
optimalFuel = mid;
high = mid - 1; // 继续寻找更小油量
} else {
low = mid + 1;
}
}
return optimalFuel;
}
// 读取输入
let input = [];
rl.on("line", (line) => {
input.push(line);
}).on("close", () => {
let [rows, cols] = input.shift().split(",").map(Number);
let grid = input.map(row => row.split(",").map(Number));
console.log(findMinimumInitialFuel(grid, rows, cols));
});
package main
import (
"container/heap"
"fmt"
"strings"
"strconv"
)
const MAX_FUEL = 100 // 车辆最大油量
// PriorityQueue 是一个最大堆,用于优先队列
type PriorityQueue struct {
items [][]int
}
func (pq *PriorityQueue) Len() int {
return len(pq.items)
}
func (pq *PriorityQueue) Less(i, j int) bool {
return pq.items[i][0] > pq.items[j][0]
}
func (pq *PriorityQueue) Swap(i, j int) {
pq.items[i], pq.items[j] = pq.items[j], pq.items[i]
}
func (pq *PriorityQueue) Push(x interface{}) {
pq.items = append(pq.items, x.([]int))
}
func (pq *PriorityQueue) Pop() interface{} {
old := pq.items
n := len(old)
x := old[n-1]
pq.items = old[0 : n-1]
return x
}
// 判断是否能到达终点
func canReachDestination(grid [][]int, initialFuel, rows, cols int) bool {
if grid[0][0] == 0 {
return false
}
fuelLeft := make([][]int, rows)
for i := range fuelLeft {
fuelLeft[i] = make([]int, cols)
for j := range fuelLeft[i] {
fuelLeft[i][j] = -1
}
}
if grid[0][0] == -1 {
fuelLeft[0][0] = MAX_FUEL
} else {
fuelLeft[0][0] = initialFuel - grid[0][0]
}
if fuelLeft[0][0] < 0 {
return false
}
pq := &PriorityQueue{}
heap.Init(pq)
heap.Push(pq, []int{fuelLeft[0][0], 0, 0})
directions := [][2]int{{0, 1}, {1, 0}, {0, -1}, {-1, 0}} // 四个移动方向
for pq.Len() > 0 {
item := heap.Pop(pq).([]int)
fuel, r, c := item[0], item[1], item[2]
if r == rows-1 && c == cols-1 {
return true
}
for _, dir := range directions {
nr, nc := r+dir[0], c+dir[1]
if nr >= 0 && nr < rows && nc >= 0 && nc < cols && grid[nr][nc] != 0 {
var newFuel int
if grid[nr][nc] == -1 {
newFuel = MAX_FUEL
} else {
newFuel = fuel - grid[nr][nc]
}
if newFuel > fuelLeft[nr][nc] {
fuelLeft[nr][nc] = newFuel
heap.Push(pq, []int{newFuel, nr, nc})
}
}
}
}
return false
}
// 二分查找最小初始油量
func findMinimumInitialFuel(grid [][]int, rows, cols int) int {
low, high := 0, MAX_FUEL
var optimalFuel = -1
for low <= high {
mid := (low + high) / 2
if canReachDestination(grid, mid, rows, cols) {
optimalFuel = mid
high = mid - 1
} else {
low = mid + 1
}
}
return optimalFuel
}
func main() {
var rows, cols int
fmt.Scanf("%d,%d\n", &rows, &cols)
grid := make([][]int, rows)
for i := 0; i < rows; i++ {
var line string
fmt.Scanln(&line)
values := strings.Split(line, ",")
grid[i] = make([]int, cols)
for j, value := range values {
grid[i][j], _ = strconv.Atoi(value)
}
}
fmt.Println(findMinimumInitialFuel(grid, rows, cols))
}