华为OD机试 2025 B卷 - 智能驾驶 (C++ & Python & JAVA & JS & GO)

智能驾驶

华为OD机试真题目录点击查看: 华为OD机试2025B卷真题题库目录|机考题库 + 算法考点详解

华为OD机试2025B卷 200分题型

题目描述

有一辆汽车需要从 m * n 的地图左上角(起点)开往地图的右下角(终点),去往每一个地区都需要消耗一定的油量,加油站可进行加油。

请你计算汽车确保从从起点到达终点时所需的最少初始油量。说明:

  1. 智能汽车可以上下左右四个方向移动
  2. 地图上的数字取值是 0 或 -1 或 正整数:
    • -1 :表示加油站,可以加满油,汽车的油箱容量最大为100;
    • 0 :表示这个地区是障碍物,汽车不能通过
    • 正整数:表示汽车走过这个地区的耗油量

如果汽车无论如何都无法到达终点,则返回 -1

输入描述

第一行为两个数字,M,N,表示地图的大小为 M N。0 < M,N ≤ 200
后面一个 M * N 的矩阵,其中的值是 0 或 -1 或正整数,加油站的总数不超过 200 个

输出描述

如果汽车无论如何都无法到达终点,则返回 -1。如果汽车可以到达终点,则返回最少的初始油量

示例1

输入

2,2
10,20
30,40

输出

70

说明

行走的路线为:右→下

示例2

输入

4,4
10,30,30,20
30,30,-1,10
0,20,20,40
10,-1,30,40

输出

70

说明

行走的路线为:右→右→下→下→下→右

题解

思路:二分 + BFS

  1. 使用二分去枚举汽车初始油量,利用BFS算法去判断二分确定的油是否满足车从左上角 -> 右下角。
  2. 注意事项(特殊点):
    • 汽车在经过加油站可以加油。
    • 起点为0,代表绝不可能完成左上角 -> 右下角的行动,因为0为障碍物。
  3. 初始设置result = -1记录可行的最小结果, 二分初始设置left = 0, right = 100 (汽车最大存储油容量),每次二分枚举mid = (left + right) / 2,使用BFS进行判断能否从左上角到右小角
    • 能:更新right = mid - 1 , result = mid
    • 不能: 更新left = mid + 1
  4. 执行3操作直到left > right结束。最后输出result即可。
  5. BFS的判断逻辑:使用优先队列模拟判断给定初始油量能否从左上角到达右下角。可以使用fuelLeft[][]数组进行剪枝,fuelLeft[i][j]剩余的最多油量进行剪枝。具体逻辑可以参照下面的代码。

c++

#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;
}

Java

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));
    }
}

Python

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))

JavaScript

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));
});

Go

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))
}

你可能感兴趣的:(华为od,华为OD机试,华为OD机试,2025B卷,华为OD2025B卷,华为OD机考2025B卷)