Skip to content

Commit 710f737

Browse files
authoredSep 16, 2023
feat: add solutions to lc problem: No.1883 (doocs#1636)
No.1883.Minimum Skips to Arrive at Meeting On Time
1 parent d10c94b commit 710f737

File tree

7 files changed

+391
-110
lines changed

7 files changed

+391
-110
lines changed
 

‎solution/1800-1899/1883.Minimum Skips to Arrive at Meeting On Time/README.md

+142-36
Original file line numberDiff line numberDiff line change
@@ -69,16 +69,21 @@
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

@@ -90,22 +95,36 @@
9095
class 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:
117136
class 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

Comments
 (0)
Please sign in to comment.