[华为OD]BFS C卷 200 智能驾驶

题目:

有一辆汽车需要从m*n的地图的左上角(起点)开往地图的右下角(终点),去往每一个地区都需 

要消耗一定的油量,加油站可进行加油

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

(1)智能汽车可以上下左右四个方向移动1

⑵地图上的数字取值是0或-1或者正整数:

-1:表示加油站,可以加满油,汽车的油箱容量最大为100;

0:表示这个地区是障碍物,汽车不能通过

正整数:表示汽车走过这个地区的耗油量

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

输入描述

第一行为两个数字,M, V,表示地图的大小为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

示例3

输入

4,5

10,0,30,-1,10 

30,0,20,0,20 

10,0,10,0,30 

10,-1,30,0,10 

输出

60

示例4

输入

4,4

10,30,30,20 

30,30,20,10 

10,20,10,40 

10,20,30,40 

输出

-1

题解:这个题目要计算最少初始油料,那么如果经过加油站的话,明显就要直接加满油。

比较明显的BFS题目。但是需要判断到加油站的情况。由于油箱容量100,那么我们出发时候就将当前油量设置为100。

依旧还是需要定义一个内部类,参数有x,y坐标。这个里面就加了,初始油量originalOil,当前坐标走完需要油量needOil,也就是矩阵中当前的值。以及汽车在这个坐标的剩余油量restOil,还有一个bool值,是否有在加油站加过油。

1)如果到加油站时候,车辆没有加过油,那么从出发到这个加油站的初始油量(刚出发时候初始油量)就可以变为100减去当前剩余油量了。

2)当BFS向下一坐标搜索的时候,如果restOil剩余油量不足以满足去下一个坐标需要的油量needOil,那么就继续往下搜索

3)在到终点的时候,如果没有加过油,那么如果剩余油量>0,那么这个路径走下来的初始油量应该可以变成100减去当前剩余油量

4)当走到任意坐标时候,油量足够,而且汽车加过油,那么初始油量应该不变,因为加过油,剩余油量在加油站那个坐标直接变为100了

5)走过一个坐标,那么这个坐标访问标记visit[x][y]=1;

这个里面可以看到有一个难点就是可能有两条路线能经过同一个加油站,两条路径油量不同,如何确保最终是最少油量经过这个加油站。这边采用的是一个map<String,Integer> oilStations来解决表示的是这个加油站坐标和来这个加油站最少得油量。因为在初始化扫描的时候当矩matrixs[i][j]==-1,就是加油站,那么此时就初始化这个加油站油量为Integer.MaxValue.

6)那么在经过加油站的坐标时候,加油站坐标的visit[x][y],还是为0,不能变为1,防止其他路径更少油量,由于visit[x][y]==1,而不能到加油站,结果就不对。此时,先根据oilStations,拿到抵达这个加油站当前的最少油量prsentL

### 题目描述 智能汽车可以上下左右四个方向移动,地图上的数字取值是 0 或 -1 或正整数: - -1 :表示加油站,可以加满油,汽车的油箱容量最大为 100; - 0 :表示这个地区是障碍物,汽车不能通过; - 正整数:表示汽车走过这个地区的耗油量。 如果汽车无论如何都无法到达终点,则返回 -1 [^1]。 ### 示例解析 输入示例: ```plaintext 2 2 10 20 30 40 ``` 2 2 表示地图是 2 行 2 列的。接下来的两行数字表示地图的具体内容:10 20 30 40 ,起点在(0, 0),耗油量为 10。终点在(1, 1),耗油量为 40。从起点到终点只有一条路径,即(0, 0) -> (1, 1)。 输出示例: ```plaintext 70 ``` 解析:从起点(0, 0)出发,耗油量为 10,到达(1, 1)耗油量为 40,总共需要初始油量 70 [^2]。 ### 解题思路 可以使用广度优先搜索(BFS)来解决这个问题。具体步骤如下: 1. 初始化队列,将起点及初始油量信息加入队列。 2. 定义方向数组,用于表示上下左右四个方向。 3. 遍历队列,取出当前位置和油量信息。 4. 检查当前位置是否为终点,如果是则更新最小初始油量。 5. 遍历四个方向,计算新位置和新油量。 6. 检查新位置是否合法(在地图范围内、不是障碍物),如果是加油站则加满油。 7. 如果新油量大于 0 且新状态未被访问过,则将新状态加入队列。 ### 代码示例(Python) ```python from collections import deque def min_initial_fuel(grid): rows, cols = len(grid), len(grid[0]) # 定义四个方向:上、下、左、右 directions = [(-1, 0), (1, 0), (0, -1), (0, 1)] # 初始化最小初始油量为无穷大 min_fuel = float('inf') # 初始化队列,队列元素为 (x, y, current_fuel, initial_fuel) queue = deque([(0, 0, 0, 0)]) # 初始化访问集合,记录已经访问过的状态 visited = set() while queue: x, y, current_fuel, initial_fuel = queue.popleft() # 如果到达终点,更新最小初始油量 if x == rows - 1 and y == cols - 1: min_fuel = min(min_fuel, initial_fuel) continue # 遍历四个方向 for dx, dy in directions: new_x, new_y = x + dx, y + dy # 检查新位置是否合法 if 0 <= new_x < rows and 0 <= new_y < cols and grid[new_x][new_y] != 0: new_fuel = current_fuel if grid[new_x][new_y] == -1: # 如果是加油站,加满油 new_fuel = 100 else: # 否则消耗油量 new_fuel -= grid[new_x][new_y] # 如果新油量小于 0,需要增加初始油量 if new_fuel < 0: initial_fuel += abs(new_fuel) new_fuel = 0 # 新状态 new_state = (new_x, new_y, new_fuel, initial_fuel) # 如果新状态未被访问过,加入队列 if new_state not in visited: visited.add(new_state) queue.append(new_state) # 如果无法到达终点,返回 -1 return min_fuel if min_fuel != float('inf') else -1 # 示例输入 grid = [ [10, 20], [30, 40] ] print(min_initial_fuel(grid)) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值