6969
7070<!-- 这里可写通用的实现逻辑 -->
7171
72- " 动态规划"实现。
72+ ** 方法一: 动态规划**
7373
74- 定义 ` dp [i][j]` 表示前 i 段道路,跳过了 j 次的最短路程(耗时也一样) 。
74+ 我们定义 $f [ i] [ j ] $ 表示考虑前 $i$ 条道路,恰好跳过 $j$ 次休息时间的最短用时。初始时 $f [ 0 ] [ 0 ] =0,ドル其余 $f [ i ] [ j ] =\infty$ 。
7575
76- 考虑最后一段道路 ` dist[i - 1] ` 是否跳过 :
76+ 由于我们可以选择跳过或者不跳过第 $i$ 条道路的休息时间,因此我们可以列出状态转移方程 :
7777
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+ $$
8081
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$ 是道路的数量。
8287
8388<!-- tabs:start -->
8489
9095class Solution :
9196 def minSkips (self , dist : List[int ], speed : int , hoursBefore : int ) -> int :
9297 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 ):
96120 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
109128 return - 1
110129```
111130
@@ -117,36 +136,123 @@ class Solution:
117136class Solution {
118137 public int minSkips (int [] dist , int speed , int hoursBefore ) {
119138 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 );
125142 }
126- dp[0 ][0 ] = 0 ;
143+ f[0 ][0 ] = 0 ;
144+ double eps = 1e-8 ;
127145 for (int i = 1 ; i <= n; ++ i) {
128146 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);
133150 }
134151 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);
137153 }
138154 }
139155 }
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 ;
143159 }
144160 }
145161 return - 1 ;
146162 }
147163}
148164```
149165
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+ 150256### ** ...**
151257
152258```
0 commit comments