题目:
给你一个整数 hoursBefore
,表示你要前往会议所剩下的可用小时数。要想成功抵达会议现场,你必须途经 n
条道路。道路的长度用一个长度为 n
的整数数组 dist
表示,其中 dist[i]
表示第 i
条道路的长度(单位:千米)。另给你一个整数 speed
,表示你在道路上前进的速度(单位:千米每小时)。
当你通过第 i
条路之后,就必须休息并等待,直到 下一个整数小时 才能开始继续通过下一条道路。注意:你不需要在通过最后一条道路后休息,因为那时你已经抵达会议现场。
- 例如,如果你通过一条道路用去
1.4
小时,那你必须停下来等待,到2
小时才可以继续通过下一条道路。如果通过一条道路恰好用去2
小时,就无需等待,可以直接继续。
然而,为了能准时到达,你可以选择 跳过 一些路的休息时间,这意味着你不必等待下一个整数小时。注意,这意味着与不跳过任何休息时间相比,你可能在不同时刻到达接下来的道路。
- 例如,假设通过第
1
条道路用去1.4
小时,且通过第2
条道路用去0.6
小时。跳过第1
条道路的休息时间意味着你将会在恰好2
小时完成通过第2
条道路,且你能够立即开始通过第3
条道路。
返回准时抵达会议现场所需要的 最小跳过次数 ,如果 无法准时参会 ,返回 -1
。
提示:
n == dist.length
1 <= n <= 1000
1 <= dist[i] <= 105
1 <= speed <= 106
1 <= hoursBefore <= 107
思考:
今天的题真的毫无思路,感谢lt老师倾情讲解思密达,思路如下:
从第一段路开始走,每一段路都会遇到一个选择:当前这段路的休息时间跳不跳过?
问题是“直到走到最后一段路(无需休息时间),能在限制时间前到达的情况下最少的跳过次数是多少?” ----> 我们在走到第i段路的时候,都计算在前面i段路中跳过j次休息时间的情况下,消耗的最少时间 ----> 这里把消耗的时间转换成路程来计算,那么用一个二维数组dp记录,dp[i][j]表示走过i条道路,并跳过j次休息时间时,最短的路径。
对于dp[i][j],可以由两种方式得到:
- 第i段跳过休息时间:
- 第i段不跳过休息时间:
dp[i][j]即为上述两种结果的更小值。
特殊的,
- 当j为0时,代表全部不跳过,
- 当j等于i时,代表全部跳过,
- 当i为n时,代表到了最后一段路,不需要休息,
代码如下:
class Solution(object):
def minSkips(self, dist, speed, hoursBefore):
"""
:type dist: List[int]
:type speed: int
:type hoursBefore: int
:rtype: int
"""
def ceil(dist, speed):
if dist % speed == 0:
return dist/speed
else:
return dist//speed +1
if sum(dist) > hoursBefore * speed:
return -1
n = len(dist)
dp = [[float('inf') for _ in range(n+1)] for _ in range(n+1)]
# dp[i][j]表示走过i条道路,并跳过j次休息时间时,最短的路径
# 休息时间也用路径来度量,以保持一致
dp[0][0] = 0
for i in range(1, n+1):
for j in range(0, i+1):
if j == 0:
dp[i][j] = dp[i-1][j] + ceil(dist[i-1], speed) * speed
elif j == i:
dp[i][j] = dp[i-1][j-1] + dist[i-1]
else:
res_1 = dp[i-1][j-1] + dist[i-1] # 跳过当前的休息时间
res_2 = ceil((dp[i-1][j] + dist[i-1]), speed) * speed # 不跳过当前的休息时间
dp[i][j] = min(res_1, res_2)
if i == n:
dp[i][j] = dp[i-1][j] + dist[i-1]
for k in range(0, n+1):
if dp[n][k] <= speed * hoursBefore:
return k
提交通过: