问题描述:
汽车从起点出发驶向目的地,该目的地位于出发位置东面
target
英里处。
沿途有加油站,每个station[i]
代表一个加油站,它位于出发位置东面 station[i][0]
英里处,并且有 station[i][1]
升汽油。
假设汽车油箱的容量是无限的,其中最初有 startFuel 升燃料。它每行驶 1 英里就会用掉 1 升汽油。
当汽车到达加油站时,它可能停下来加油,将所有汽油从加油站转移到汽车中。
为了到达目的地,汽车所必要的最低加油次数是多少?如果无法到达目的地,则返回-1
。
注意:如果汽车到达加油站时剩余燃料为 0,它仍然可以在那里加油。如果汽车到达目的地时剩余燃料为 0,仍然认为它已经到达目的地。
示例 1:
输入:target = 100, startFuel = 10, stations = [[10,60],[20,30],[30,30],[60,40]]
输出:2
解释:我们出发时有 10 升燃料。我们开车来到距起点 10 英里处的加油站,消耗 10 升燃料。将汽油从 0 升加到 60 升。然后,我们从 10 英里处的加油站开到 60 英里处的加油站(消耗 50 升燃料),并将汽油从 10 升加到 50 升。然后我们开车抵达目的地。我们沿途在1两个加油站停靠,所以返回 2 。
提示:
1 <= target, startFuel, stations[i][1] <= 10^9
0 <= stations.length <= 500
0 < stations[0][0] < stations[1][0] < ... < stations[stations.length-1][0] < target
问题分析:
这个题目使用动态规划的思想,基本思路,设dp[i]表示第i次加油之后可以达到的最远距离,很显然,i <= 加油站的个数
,求出dp之后,从头遍历一边,找到第一个 dp[i] >= target 的 i ,就是最少的加油次数,如果没有就返回-1。
(1)问题 dp[i] 怎么求? 首先,从头开遍历加油站,每当遍历到第i个加油站时,dp[t+1] = max(dp[t+1], dp[t] + arr[i])
,其中t+1 <= i
,然后依次,从后向前更新dp,可以这样理解,dp[t] 再加一次油arr[i],得到的新的dp[t+1]是否是比之前的dp[t+1]大?如果大就更新。依次遍历递推,直至结束。值得思考是的,仔细观察递推公式:dp[t+1] = max(dp[t+1], dp[t] + arr[i])
你会发现,无论更新与否,dp[t+1] 始终代表的是第 t+1 次加油。
Python3实现:
# @Time :2018/7/25
# @Author :Yinxing
# 动态规划 时间复杂度 O(N^2K) 空间复杂度 O(N)
class Solution:
def minRefuelStops(self, target, startFuel, stations):
dp = [startFuel] + [0] * len(stations) # 初始化dp
for i, (loc, cap) in enumerate(stations): # 遍历加油站
for t in range(i, -1, -1):
if dp[t] >= loc: # 如果 第 t 加油后,可以到达 当前加油站的位置。
dp[t+1] = max(dp[t+1], dp[t] + cap) # 尝试的更新dp
for i, d in enumerate(dp): # 遍历出最小次数
if d >= target: return i
return -1
if __name__ == '__main__':
solu = Solution()
target, startFuel, stations = 100, 10, [[10, 60], [20, 30], [30, 30], [60, 40]]
print(solu.minRefuelStops(target, startFuel, stations))
欢迎指正哦。