69
69
70
70
<!-- 这里可写通用的实现逻辑 -->
71
71
72
- “ 动态规划”实现。
72
+ ** 方法一: 动态规划**
73
73
74
- 定义 ` dp [i][j]` 表示前 i 段道路,跳过了 j 次的最短路程(耗时也一样) 。
74
+ 我们定义 $f [ i] [ j ] $ 表示考虑前 $i$ 条道路,恰好跳过 $j$ 次休息时间的最短用时。初始时 $f [ 0 ] [ 0 ] =0$,其余 $f [ i ] [ j ] =\infty$ 。
75
75
76
- 考虑最后一段道路 ` dist[i - 1] ` 是否跳过 :
76
+ 由于我们可以选择跳过或者不跳过第 $i$ 条道路的休息时间,因此我们可以列出状态转移方程 :
77
77
78
- - 若没有跳过,那么 ` dp[i][j] = ⌈dp[i - 1][j] + dist[i - 1] / speed⌉ `
79
- - 若跳过,那么 ` dp[i][j] = dp[i - 1][j - 1] + dist[i - 1] / speed `
78
+ $$
79
+ f[i][j]=\min\left\{\begin{aligned} \lceil f[i-1][j]+\frac{d_i}{s}\rceil & \text{不跳过第 $i$ 条道路的休息时间} \\ f[i-1][j-1]+\frac{d_i}{s} & \text{跳过第 $i$ 条道路的休息时间} \end{aligned}\right.
80
+ $$
80
81
81
- 综合两种情况,` dp[i][j] = min{⌈dp[i - 1][j] + dist[i - 1] / speed⌉, dp[i - 1][j - 1] + dist[i - 1] / speed} ` 。
82
+ 其中 $\lceil x\rceil$ 表示将 $x$ 向上取整。需要注意的是,由于我们需要保证恰好跳过 $j$ 次休息时间,因此我们必须有 $j\le i$;另外,如果 $j=0$,不能跳过任何休息时间。
83
+
84
+ 由于浮点数运算以及向上取整运算可能会带来精度误差,因此我们引入一个常量 $eps = 10^{-8}$ 表示一个极小的正实数,在浮点数取整前先减去 $eps$,最后在比较 $f[ n] [ j ] $ 和 $hoursBefore$ 时,需要加上 $eps$。
85
+
86
+ 时间复杂度 $O(n^2)$,空间复杂度 $O(n^2)$。其中 $n$ 是道路的数量。
82
87
83
88
<!-- tabs:start -->
84
89
90
95
class Solution :
91
96
def minSkips (self , dist : List[int ], speed : int , hoursBefore : int ) -> int :
92
97
n = len (dist)
93
- dp = [[inf] * (n + 1 ) for _ in range (n + 1 )]
94
- dp[0 ][0 ] = 0
95
- for i in range (1 , n + 1 ):
98
+ f = [[inf] * (n + 1 ) for _ in range (n + 1 )]
99
+ f[0 ][0 ] = 0
100
+ eps = 1e-8
101
+ for i, x in enumerate (dist, 1 ):
102
+ for j in range (i + 1 ):
103
+ if j < i:
104
+ f[i][j] = min (f[i][j], ceil(f[i - 1 ][j] + x / speed - eps))
105
+ if j:
106
+ f[i][j] = min (f[i][j], f[i - 1 ][j - 1 ] + x / speed)
107
+ for j in range (n + 1 ):
108
+ if f[n][j] <= hoursBefore + eps:
109
+ return j
110
+ return - 1
111
+ ```
112
+
113
+ ``` python
114
+ class Solution :
115
+ def minSkips (self , dist : List[int ], speed : int , hoursBefore : int ) -> int :
116
+ n = len (dist)
117
+ f = [[inf] * (n + 1 ) for _ in range (n + 1 )]
118
+ f[0 ][0 ] = 0
119
+ for i, x in enumerate (dist, 1 ):
96
120
for j in range (i + 1 ):
97
- if i != j:
98
- # 没有跳过
99
- dp[i][j] = min (
100
- dp[i][j],
101
- ((dp[i - 1 ][j] + dist[i - 1 ] - 1 ) // speed + 1 ) * speed,
102
- )
103
- if j > 0 :
104
- # 跳过
105
- dp[i][j] = min (dp[i][j], dp[i - 1 ][j - 1 ] + dist[i - 1 ])
106
- for i in range (n + 1 ):
107
- if dp[n][i] <= hoursBefore * speed:
108
- return i
121
+ if j < i:
122
+ f[i][j] = min (f[i][j], ((f[i - 1 ][j] + x - 1 ) // speed + 1 ) * speed)
123
+ if j:
124
+ f[i][j] = min (f[i][j], f[i - 1 ][j - 1 ] + x)
125
+ for j in range (n + 1 ):
126
+ if f[n][j] <= hoursBefore * speed:
127
+ return j
109
128
return - 1
110
129
```
111
130
@@ -117,36 +136,123 @@ class Solution:
117
136
class Solution {
118
137
public int minSkips (int [] dist , int speed , int hoursBefore ) {
119
138
int n = dist. length;
120
- int [][] dp = new int [n + 1 ][n + 1 ];
121
- for (int i = 0 ; i <= n; ++ i) {
122
- for (int j = 0 ; j <= n; ++ j) {
123
- dp[i][j] = Integer . MAX_VALUE ;
124
- }
139
+ double [][] f = new double [n + 1 ][n + 1 ];
140
+ for (int i = 0 ; i <= n; i++ ) {
141
+ Arrays . fill(f[i], 1e20 );
125
142
}
126
- dp[0 ][0 ] = 0 ;
143
+ f[0 ][0 ] = 0 ;
144
+ double eps = 1e-8 ;
127
145
for (int i = 1 ; i <= n; ++ i) {
128
146
for (int j = 0 ; j <= i; ++ j) {
129
- if (i != j) {
130
- // 没有跳过
131
- dp[i][j] = Math . min(
132
- dp[i][j], ((dp[i - 1 ][j] + dist[i - 1 ] - 1 ) / speed + 1 ) * speed);
147
+ if (j < i) {
148
+ f[i][j] = Math . min(
149
+ f[i][j], Math . ceil(f[i - 1 ][j]) + 1.0 * dist[i - 1 ] / speed - eps);
133
150
}
134
151
if (j > 0 ) {
135
- // 跳过
136
- dp[i][j] = Math . min(dp[i][j], dp[i - 1 ][j - 1 ] + dist[i - 1 ]);
152
+ f[i][j] = Math . min(f[i][j], f[i - 1 ][j - 1 ] + 1.0 * dist[i - 1 ] / speed);
137
153
}
138
154
}
139
155
}
140
- for (int i = 0 ; i <= n; ++ i ) {
141
- if (dp [n][i ] <= hoursBefore * speed ) {
142
- return i ;
156
+ for (int j = 0 ; j <= n; ++ j ) {
157
+ if (f [n][j ] <= hoursBefore + eps ) {
158
+ return j ;
143
159
}
144
160
}
145
161
return - 1 ;
146
162
}
147
163
}
148
164
```
149
165
166
+ ### ** C++**
167
+
168
+ ``` cpp
169
+ class Solution {
170
+ public:
171
+ int minSkips(vector<int >& dist, int speed, int hoursBefore) {
172
+ int n = dist.size();
173
+ vector<vector<double >> f(n + 1, vector<double >(n + 1, 1e20));
174
+ f[ 0] [ 0 ] = 0;
175
+ double eps = 1e-8;
176
+ for (int i = 1; i <= n; ++i) {
177
+ for (int j = 0; j <= i; ++j) {
178
+ if (j < i) {
179
+ f[ i] [ j ] = min(f[ i] [ j ] , ceil(f[ i - 1] [ j ] + dist[ i - 1] * 1.0 / speed - eps));
180
+ }
181
+ if (j) {
182
+ f[ i] [ j ] = min(f[ i] [ j ] , f[ i - 1] [ j - 1 ] + dist[ i - 1] * 1.0 / speed);
183
+ }
184
+ }
185
+ }
186
+ for (int j = 0; j <= n; ++j) {
187
+ if (f[ n] [ j ] <= hoursBefore + eps) {
188
+ return j;
189
+ }
190
+ }
191
+ return -1;
192
+ }
193
+ };
194
+ ```
195
+
196
+ ### **Go**
197
+
198
+ ```go
199
+ func minSkips(dist []int, speed int, hoursBefore int) int {
200
+ n := len(dist)
201
+ f := make([][]float64, n+1)
202
+ for i := range f {
203
+ f[i] = make([]float64, n+1)
204
+ for j := range f[i] {
205
+ f[i][j] = 1e20
206
+ }
207
+ }
208
+ f[0][0] = 0
209
+ eps := 1e-8
210
+ for i := 1; i <= n; i++ {
211
+ for j := 0; j <= i; j++ {
212
+ if j < i {
213
+ f[i][j] = math.Min(f[i][j], math.Ceil(f[i-1][j]+float64(dist[i-1])/float64(speed)-eps))
214
+ }
215
+ if j > 0 {
216
+ f[i][j] = math.Min(f[i][j], f[i-1][j-1]+float64(dist[i-1])/float64(speed))
217
+ }
218
+ }
219
+ }
220
+ for j := 0; j <= n; j++ {
221
+ if f[n][j] <= float64(hoursBefore) {
222
+ return j
223
+ }
224
+ }
225
+ return -1
226
+ }
227
+ ```
228
+
229
+ ### ** TypeScript**
230
+
231
+ ``` ts
232
+ function minSkips(dist : number [], speed : number , hoursBefore : number ): number {
233
+ const n = dist .length ;
234
+ const f = Array .from ({ length: n + 1 }, () => Array .from ({ length: n + 1 }, () => Infinity ));
235
+ f [0 ][0 ] = 0 ;
236
+ const eps = 1e-8 ;
237
+ for (let i = 1 ; i <= n ; ++ i ) {
238
+ for (let j = 0 ; j <= i ; ++ j ) {
239
+ if (j < i ) {
240
+ f [i ][j ] = Math .min (f [i ][j ], Math .ceil (f [i - 1 ][j ] + dist [i - 1 ] / speed - eps ));
241
+ }
242
+ if (j ) {
243
+ f [i ][j ] = Math .min (f [i ][j ], f [i - 1 ][j - 1 ] + dist [i - 1 ] / speed );
244
+ }
245
+ }
246
+ }
247
+ for (let j = 0 ; j <= n ; ++ j ) {
248
+ if (f [n ][j ] <= hoursBefore + eps ) {
249
+ return j ;
250
+ }
251
+ }
252
+ return - 1 ;
253
+ }
254
+ ```
255
+
150
256
### ** ...**
151
257
152
258
```
0 commit comments