一、题目
1、题目描述
给你一个整数
hoursBefore
,表示你要前往会议所剩下的可用小时数。要想成功抵达会议现场,你必须途经n
条道路。道路的长度用一个长度为n
的整数数组dist
表示,其中dist[i]
表示第i
条道路的长度(单位:千米)。另给你一个整数speed
,表示你在道路上前进的速度(单位:千米每小时)。当你通过第
i
条路之后,就必须休息并等待,直到 下一个整数小时 才能开始继续通过下一条道路。注意:你不需要在通过最后一条道路后休息,因为那时你已经抵达会议现场。
- 例如,如果你通过一条道路用去
1.4
小时,那你必须停下来等待,到2
小时才可以继续通过下一条道路。如果通过一条道路恰好用去2
小时,就无需等待,可以直接继续。然而,为了能准时到达,你可以选择 跳过 一些路的休息时间,这意味着你不必等待下一个整数小时。注意,这意味着与不跳过任何休息时间相比,你可能在不同时刻到达接下来的道路。
- 例如,假设通过第
1
条道路用去1.4
小时,且通过第2
条道路用去0.6
小时。跳过第1
条道路的休息时间意味着你将会在恰好2
小时完成通过第2
条道路,且你能够立即开始通过第3
条道路。返回准时抵达会议现场所需要的 最小跳过次数 ,如果 无法准时参会 ,返回
-1
。
2、接口描述
python3
class Solution:
def minSkips(self, dist: List[int], speed: int, hoursBefore: int) -> int:
cpp
class Solution {
public:
int minSkips(vector<int>& dist, int speed, int hoursBefore) {
}
};
3、原题链接
二、解题报告
1、思路分析
看到1e3,结合题意,能联想到二维的O(1)状态转移dp或者一维O(n)状态转移线性dp
我们考虑状态设计,每个位置都有跳过rest或不跳过两种选择
定义状态f[i][j]为前i 条路跳过j次的等效行动距离
等效行动距离:假如路径长度为1.5,速度为2,那么不跳过就是要1h,相当于走了2
假如跳过,就是走了1.5
那么有状态转移
f[i][j] = min(f[i - 1][j - 1] + dst[j], f[i - 1][j] + ceil(dst[j] / speed) * speed)
然后发现可以:
滚动数组优化
用整形存储代替浮点数存储进一步优化空间
详细看代码
2、复杂度
时间复杂度:O(n^2) 空间复杂度:O(n)
3、代码详解
python3
class Solution:
def minSkips(self, dist: List[int], speed: int, hoursBefore: int) -> int:
n = len(dist)
f = [[inf] * (n + 1) for _ in range(2)]
f[0][0] = 0
for i in range(1, n + 1):
print("")
for j in range(i + 1):
f[i % 2][j] = inf
if i > j:
f[i % 2][j] = min(f[i % 2][j], speed + (f[(i - 1) % 2][j] + dist[i - 1] - 1) // speed * speed)
if i:
f[i % 2][j] = min(f[i % 2][j], f[(i - 1) % 2][j - 1] + dist[i - 1])
for i in range(n + 1):
if f[n % 2][i] <= speed * hoursBefore:
return i
return -1
cpp
class Solution {
public:
typedef long long LL;
int minSkips(vector<int>& dist, LL speed, int hoursBefore) {
int n = dist.size();
vector<vector<LL>> f(2, vector<LL>(n + 1, 1e18));
f[0][0]= 0;
for(int i = 1; i <= n; i++)
for(int j = 0; j <= i; j++){
f[i % 2][j] = 1e18;
if(i > j)
f[i % 2][j] = min(f[i % 2][j], speed + (f[(i - 1) % 2][j] + dist[i - 1] - 1) / speed * speed);
if(j)
f[i % 2][j] = min(f[i % 2][j], f[(i - 1) % 2][j - 1] + dist[i - 1]);
}
for(int j = 0; j <= n; j++)
if(f[n % 2][j] <= hoursBefore * speed)
return j;
return -1;
}
};