题目:绿洲之旅:最少次数补给探索
小U正在准备穿越一片广阔的沙漠。沙漠里有多个绿洲,每个绿洲设有补给站。所有补给站的收费相同,但提供的水是不同。从起点到终点共有(D)公里,小U需要规划在哪 些补给站停留,以保证整个旅途中水的供应 起点到终点的距离为 D)公里,小U初始携带 ) 升水,每行走1公里消耗1升水,小U希望涌过最少的补给次数安全到认终点,每个补给站的位置电 positioni1 表示,距 离起点的公里数,supply[i]表示该站可以提供的水量,单位为升。 请你帮助小U计算,要安全到达终点至少需要补给几次,或者判断是否根本无法到达终点,此时输出-1。
题目分析
小U需要穿越一片沙漠,起点和终点之间的距离为 𝐷 D 公里,每行走 1 公里消耗 1 升水。小U初始携带 𝑊 W 升水,沙漠中有多个补给站,每个补给站在不同的位置提供不同的水量。小U希望通过最少的补给次数安全到达终点。
输入
- 𝐷:终点到起点的总距离。
- 𝑊:小U初始携带的水量。
- position:一个数组,表示每个补给站距离起点的公里数。
- supply:一个数组,与 position 对应,表示每个补给站可以提供的水量。
输出##
- 到达终点所需的最少补给次数。如果无法到达终点,则输出 -1。
题目特点
- 贪心策略可以解决本问题。
- 每次选择最优的补给站(提供最多水量)以减少补给次数。
- 若当前水量不足以支持前进,必须回退到前一个能补充水量的绿洲。
解题思路
思路概述
本题适合用贪心算法解决,整体思路如下:
- 模拟小U从起点向终点行进的过程。
- 当前水量不足以到达下一个补给站时,从已经路过的补给站中选择提供最多水量的站进行补给。
- 在遍历所有补给站后,再检查是否能直接从最后一个补给站到达终点。
- 若在任何情况下无法获得足够的水量以继续前进,则返回 -1。
贪心核心点
每次补给时选择当前可用补给站中提供最多水量的站,使用最大堆(优先队列)来实现这个需求。
关键步骤
- 初始化数据结构: 使用一个最大堆存储已经路过的补给站的水量。
- 遍历补给站:
- 计算当前水量能否支持小U到达下一个补给站。
- 如果不能,反复从最大堆中取出最大的水量进行补给,直到可以到达下一个站或无法补给为止。
- 特殊情况处理:
- 在到达终点之前,若当前水量仍然不足以支持小U到达终点,继续补给;若无水可补则返回 -1。
- 返回结果: 输出最少的补给次数。
关键代码解析
初始化变量
def solution(d, w, position, supply):
# 初始化最大堆
max_heap = []
heapq.heapify(max_heap)
current_water 表示当前剩余的水量。
current_position 表示小U当前所在的位置。
refills 记录补给次数。
遍历补给站
for i in range(len(position)):
distance_to_next = position[i] - current_position
计算到下一个补给站的距离 distance_to_next。 检查当前水量是否足够:
while current_water < distance_to_next:
if not max_heap:
return -1
current_water += -heapq.heappop(max_heap)
refills += 1
如果当前水量不足,则从 max_heap 中取出最大的水量进行补给。
如果堆为空且水量仍不足,返回 -1。
更新状态
current_water -= distance_to_next
current_position = position[i]
heapq.heappush(max_heap, -supply[i])
更新当前水量和位置。
将当前补给站的水量压入堆中。
检查是否能到达终点
distance_to_end = d - current_position
while current_water < distance_to_end:
if not max_heap:
return -1
current_water += -heapq.heappop(max_heap)
refills += 1
到达所有补给站后,如果仍无法到达终点,继续从堆中补给水量。
复杂度分析
时间复杂度: 𝑂 ( 𝑁 log 𝑁 ) O(NlogN),其中 𝑁 N 是补给站的数量,每次堆操作为 𝑂 ( log 𝑁 ) O(logN)。
空间复杂度: 𝑂 ( 𝑁 ) O(N),用于存储最大堆。
总结
- 本题利用贪心策略选择每次补给的最优站点,结合最大堆实现。
- 关键在于正确管理当前水量和遍历逻辑。
- 对于需要优先选择最大值的场景,最大堆是高效解决方案。