问题描述
小U正在准备穿越一片广阔的沙漠。沙漠里有多个绿洲,每个绿洲设有补给站。所有补给站的收费相同,但提供的水量不同。从起点到终点共有 (D) 公里,小U需要规划在哪些补给站停留,以保证整个旅途中水的供应。
起点到终点的距离为 (D) 公里,小U初始携带 (W) 升水,每行走 1 公里消耗 1 升水。小U希望通过最少的补给次数安全到达终点。每个补给站的位置由 position[i] 表示,距离起点的公里数,supply[i] 表示该站可以提供的水量,单位为升。
请你帮助小U计算,要安全到达终点至少需要补给几次,或者判断是否根本无法到达终点,此时输出-1。
解决思路
数据结构选择
-
补给站信息:
position数组表示补给站的位置。supply数组表示每个补给站提供的水量。
-
优先队列:
- 使用优先队列(最大堆)来存储补给站的水量,以便在需要时选择水量最大的补给站进行补给。
算法步骤
-
初始化:
- 将终点视为一个特殊的补给站,位置为 (D),提供的水量为 0。
- 初始化当前位置为 0,当前水量为 (W),补给次数为 0。
-
遍历补给站:
- 对于每个补给站,计算从上一个位置到当前补给站的距离。
- 如果当前水量不足以到达当前补给站,则从优先队列中取出水量最大的补给站进行补给,直到水量足够。
- 如果优先队列为空且水量仍不足,则返回 -1,表示无法到达终点。
- 更新当前水量和补给次数。
-
更新状态:
- 到达当前补给站后,将当前补给站的水量放入优先队列中。
- 更新当前位置为当前补给站的位置。
-
遍历完所有补给站后,返回补给次数。
关键点:优先队列的使用:通过优先队列来动态选择水量最大的补给站进行补给,确保每次补给都是最优的。
时间复杂度:. 空间复杂度:
from queue import PriorityQueue
def solution(d, w, position, supply):
# Please write your code here
n = len(position)
position.append(d)
supply.append(0)
prev = 0 # 上一个位置
curr_w = w
count = 0 # 补给次数
q = PriorityQueue()
for i in range(n + 1):
dist = position[i] - prev
prev = position[i]
while curr_w < dist: # 从之前的补给站中选择水量最大的补给站
if q.empty():
return -1
curr_w += -q.get() # PriorityQueue默认是最小堆,所以我们取负值
count += 1
curr_w -= dist
q.put(-supply[i]) # 放入负值以实现最大堆
return count