Skip to content

Commit f2dd959

Browse files
committed
+ problem 2532
1 parent ffbe137 commit f2dd959

File tree

5 files changed

+254
-0
lines changed

5 files changed

+254
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# 2532. Time to Cross a Bridge
2+
There are `k` workers who want to move `n` boxes from the right (old) warehouse to the left (new) warehouse. You are given the two integers `n` and `k`, and a 2D integer array `time` of size `k x 4` where <code>time[i] = [right<sub>i</sub>, pick<sub>i</sub>, left<sub>i</sub>, put<sub>i</sub>]</code>.
3+
4+
The warehouses are separated by a river and connected by a bridge. Initially, all `k` workers are waiting on the left side of the bridge. To move the boxes, the <code>i<sup>th</sup></code> worker can do the following:
5+
* Cross the bridge to the right side in <code>right<sub>i</sub></code> minutes.
6+
* Pick a box from the right warehouse in <code>pick<sub>i</sub></code> minutes.
7+
* Cross the bridge to the left side in <code>left<sub>i</sub></code> minutes.
8+
* Put the box into the left warehouse in <code>put<sub>i</sub></code> minutes.
9+
10+
The <code>i<sup>th</sup></code> worker is **less efficient** than the <code>j<sup>th</sup></code> worker if either condition is met:
11+
* <code>left<sub>i</sub> + right<sub>i</sub> > left<sub>j</sub> + right<sub>j</sub></code>
12+
* <code>left<sub>i</sub> + right<sub>i</sub> == left<sub>j</sub> + right<sub>j</sub></code> and `i > j`
13+
14+
The following rules regulate the movement of the workers through the bridge:
15+
* Only one worker can use the bridge at a time.
16+
* When the bridge is unused prioritize the **least efficient** worker (who have picked up the box) on the right side to cross. If not, prioritize the **least efficient** worker on the left side to cross.
17+
* If enough workers have already been dispatched from the left side to pick up all the remaining boxes, **no more** workers will be sent from the left side.
18+
19+
Return the **elapsed minutes** at which the last box reaches the **left side of the bridge**.
20+
21+
#### Example 1:
22+
<pre>
23+
<strong>Input:</strong> n = 1, k = 3, time = [[1,1,2,1],[1,1,3,1],[1,1,4,1]]
24+
<strong>Output:</strong> 6
25+
<strong>Explanation:</strong>
26+
From 0 to 1 minutes: worker 2 crosses the bridge to the right.
27+
From 1 to 2 minutes: worker 2 picks up a box from the right warehouse.
28+
From 2 to 6 minutes: worker 2 crosses the bridge to the left.
29+
From 6 to 7 minutes: worker 2 puts a box at the left warehouse.
30+
The whole process ends after 7 minutes. We return 6 because the problem asks for the instance of time at which the last worker reaches the left side of the bridge.
31+
</pre>
32+
33+
#### Example 2:
34+
<pre>
35+
<strong>Input:</strong> n = 3, k = 2, time = [[1,5,1,8],[10,10,10,10]]
36+
<strong>Output:</strong> 37
37+
<strong>Explanation:</strong>
38+
<img src="https://assets.leetcode.com/uploads/2024/11/21/378539249-c6ce3c73-40e7-4670-a8b5-7ddb9abede11.png">
39+
The last box reaches the left side at 37 seconds. Notice, how we do not put the last boxes down, as that would take more time, and they are already on the left with the workers.
40+
</pre>
41+
42+
#### Constraints:
43+
* <code>1 <= n, k <= 10<sup>4</sup></code>
44+
* `time.length == k`
45+
* `time[i].length == 4`
46+
* <code>1 <= left<sub>i</sub>, pick<sub>i</sub>, right<sub>i</sub>, put<sub>i</sub> <= 1000</code>
47+
48+
## Solutions (Rust)
49+
50+
### 1. Solution
51+
```Rust
52+
use std::cmp::Reverse;
53+
use std::collections::BinaryHeap;
54+
55+
impl Solution {
56+
pub fn find_crossing_time(n: i32, k: i32, time: Vec<Vec<i32>>) -> i32 {
57+
let mut right_workers = BinaryHeap::new();
58+
let mut pick_workers = BinaryHeap::new();
59+
let mut left_workers = BinaryHeap::new();
60+
let mut put_workers = BinaryHeap::new();
61+
let mut pick = 0;
62+
let mut put = 0;
63+
let mut ret = 0;
64+
65+
for i in 0..time.len() {
66+
left_workers.push((time[i][2] + time[i][0], i));
67+
}
68+
69+
while put < n {
70+
while pick_workers.peek().unwrap_or(&(Reverse(i32::MAX), 0)).0 .0 <= ret {
71+
let i = pick_workers.pop().unwrap().1;
72+
right_workers.push((time[i][2] + time[i][0], i));
73+
}
74+
while put < n && put_workers.peek().unwrap_or(&(Reverse(i32::MAX), 0)).0 .0 <= ret {
75+
let i = put_workers.pop().unwrap().1;
76+
left_workers.push((time[i][2] + time[i][0], i));
77+
}
78+
79+
if let Some((_, i)) = right_workers.pop() {
80+
ret += time[i][2];
81+
put_workers.push((Reverse(ret + time[i][3]), i));
82+
put += 1;
83+
} else if pick == n || left_workers.is_empty() {
84+
ret = pick_workers
85+
.peek()
86+
.unwrap_or(&(Reverse(i32::MAX), 0))
87+
.0
88+
.0
89+
.min(put_workers.peek().unwrap_or(&(Reverse(i32::MAX), 0)).0 .0);
90+
} else if let Some((_, i)) = left_workers.pop() {
91+
ret += time[i][0];
92+
pick_workers.push((Reverse(ret + time[i][1]), i));
93+
pick += 1;
94+
}
95+
}
96+
97+
ret
98+
}
99+
}
100+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# 2532. 过桥的时间
2+
共有 `k` 位工人计划将 `n` 个箱子从右侧的(旧)仓库移动到左侧的(新)仓库。给你两个整数 `n``k`,以及一个二维整数数组 `time` ,数组的大小为 `k x 4` ,其中 <code>time[i] = [right<sub>i</sub>, pick<sub>i</sub>, left<sub>i</sub>, put<sub>i</sub>]</code> 。
3+
4+
一条河将两座仓库分隔,只能通过一座桥通行。旧仓库位于河的右岸,新仓库在河的左岸。开始时,所有 `k` 位工人都在桥的左侧等待。为了移动这些箱子,第 `i` 位工人(下标从 **0** 开始)可以:
5+
* 从左岸(新仓库)跨过桥到右岸(旧仓库),用时 <code>right<sub>i</sub></code> 分钟。
6+
* 从旧仓库选择一个箱子,并返回到桥边,用时 picki 分钟。不同工人可以同时搬起所选的箱子。
7+
* 从右岸(旧仓库)跨过桥到左岸(新仓库),用时 <code>left<sub>i</sub></code> 分钟。
8+
* 将箱子放入新仓库,并返回到桥边,用时 puti 分钟。不同工人可以同时放下所选的箱子。
9+
10+
如果满足下面任一条件,则认为工人 `i`**效率低于** 工人 `j`
11+
* <code>left<sub>i</sub> + right<sub>i</sub> > left<sub>j</sub> + right<sub>j</sub></code>
12+
* <code>left<sub>i</sub> + right<sub>i</sub> == left<sub>j</sub> + right<sub>j</sub></code> 且 `i > j`
13+
14+
工人通过桥时需要遵循以下规则:
15+
* 同时只能有一名工人过桥。
16+
* 当桥梁未被使用时,优先让右侧 **效率最低** 的工人(已经拿起盒子的工人)过桥。如果不是,优先让左侧 **效率最低** 的工人通过。
17+
* 如果左侧已经派出足够的工人来拾取所有剩余的箱子,则 **不会** 再从左侧派出工人。
18+
19+
请你返回最后一个箱子 **到达桥左侧** 的时间。
20+
21+
#### 示例 1:
22+
<pre>
23+
<strong>输入:</strong> n = 1, k = 3, time = [[1,1,2,1],[1,1,3,1],[1,1,4,1]]
24+
<strong>输出:</strong> 6
25+
<strong>解释:</strong>
26+
从 0 到 1 分钟:工人 2 通过桥到达右侧。
27+
从 1 到 2 分钟:工人 2 从右侧仓库拿起箱子。
28+
从 2 到 6 分钟:工人 2 通过桥到达左侧。
29+
从 6 到 7 分钟:工人 2 向左侧仓库放下箱子。
30+
整个过程在 7 分钟后结束。我们返回 6 因为该问题要求的是最后一名工人到达桥梁左侧的时间。
31+
</pre>
32+
33+
#### 示例 2:
34+
<pre>
35+
<strong>输入:</strong> n = 3, k = 2, time = [[1,5,1,8],[10,10,10,10]]
36+
<strong>输出:</strong> 37
37+
<strong>解释:</strong>
38+
<img src="https://assets.leetcode.com/uploads/2024/11/21/378539249-c6ce3c73-40e7-4670-a8b5-7ddb9abede11.png">
39+
最后一个盒子在37秒时到达左侧。请注意,我们并 没有 放下最后一个箱子,因为那样会花费更多时间,而且它们已经和工人们一起在左边。
40+
</pre>
41+
42+
#### 提示:
43+
* <code>1 <= n, k <= 10<sup>4</sup></code>
44+
* `time.length == k`
45+
* `time[i].length == 4`
46+
* <code>1 <= left<sub>i</sub>, pick<sub>i</sub>, right<sub>i</sub>, put<sub>i</sub> <= 1000</code>
47+
48+
## 题解 (Rust)
49+
50+
### 1. 题解
51+
```Rust
52+
use std::cmp::Reverse;
53+
use std::collections::BinaryHeap;
54+
55+
impl Solution {
56+
pub fn find_crossing_time(n: i32, k: i32, time: Vec<Vec<i32>>) -> i32 {
57+
let mut right_workers = BinaryHeap::new();
58+
let mut pick_workers = BinaryHeap::new();
59+
let mut left_workers = BinaryHeap::new();
60+
let mut put_workers = BinaryHeap::new();
61+
let mut pick = 0;
62+
let mut put = 0;
63+
let mut ret = 0;
64+
65+
for i in 0..time.len() {
66+
left_workers.push((time[i][2] + time[i][0], i));
67+
}
68+
69+
while put < n {
70+
while pick_workers.peek().unwrap_or(&(Reverse(i32::MAX), 0)).0 .0 <= ret {
71+
let i = pick_workers.pop().unwrap().1;
72+
right_workers.push((time[i][2] + time[i][0], i));
73+
}
74+
while put < n && put_workers.peek().unwrap_or(&(Reverse(i32::MAX), 0)).0 .0 <= ret {
75+
let i = put_workers.pop().unwrap().1;
76+
left_workers.push((time[i][2] + time[i][0], i));
77+
}
78+
79+
if let Some((_, i)) = right_workers.pop() {
80+
ret += time[i][2];
81+
put_workers.push((Reverse(ret + time[i][3]), i));
82+
put += 1;
83+
} else if pick == n || left_workers.is_empty() {
84+
ret = pick_workers
85+
.peek()
86+
.unwrap_or(&(Reverse(i32::MAX), 0))
87+
.0
88+
.0
89+
.min(put_workers.peek().unwrap_or(&(Reverse(i32::MAX), 0)).0 .0);
90+
} else if let Some((_, i)) = left_workers.pop() {
91+
ret += time[i][0];
92+
pick_workers.push((Reverse(ret + time[i][1]), i));
93+
pick += 1;
94+
}
95+
}
96+
97+
ret
98+
}
99+
}
100+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
use std::cmp::Reverse;
2+
use std::collections::BinaryHeap;
3+
4+
impl Solution {
5+
pub fn find_crossing_time(n: i32, k: i32, time: Vec<Vec<i32>>) -> i32 {
6+
let mut right_workers = BinaryHeap::new();
7+
let mut pick_workers = BinaryHeap::new();
8+
let mut left_workers = BinaryHeap::new();
9+
let mut put_workers = BinaryHeap::new();
10+
let mut pick = 0;
11+
let mut put = 0;
12+
let mut ret = 0;
13+
14+
for i in 0..time.len() {
15+
left_workers.push((time[i][2] + time[i][0], i));
16+
}
17+
18+
while put < n {
19+
while pick_workers.peek().unwrap_or(&(Reverse(i32::MAX), 0)).0 .0 <= ret {
20+
let i = pick_workers.pop().unwrap().1;
21+
right_workers.push((time[i][2] + time[i][0], i));
22+
}
23+
while put < n && put_workers.peek().unwrap_or(&(Reverse(i32::MAX), 0)).0 .0 <= ret {
24+
let i = put_workers.pop().unwrap().1;
25+
left_workers.push((time[i][2] + time[i][0], i));
26+
}
27+
28+
if let Some((_, i)) = right_workers.pop() {
29+
ret += time[i][2];
30+
put_workers.push((Reverse(ret + time[i][3]), i));
31+
put += 1;
32+
} else if pick == n || left_workers.is_empty() {
33+
ret = pick_workers
34+
.peek()
35+
.unwrap_or(&(Reverse(i32::MAX), 0))
36+
.0
37+
.0
38+
.min(put_workers.peek().unwrap_or(&(Reverse(i32::MAX), 0)).0 .0);
39+
} else if let Some((_, i)) = left_workers.pop() {
40+
ret += time[i][0];
41+
pick_workers.push((Reverse(ret + time[i][1]), i));
42+
pick += 1;
43+
}
44+
}
45+
46+
ret
47+
}
48+
}

README.md

+3
Original file line numberDiff line numberDiff line change
@@ -1651,6 +1651,7 @@
16511651
[2526][2526l]|[Find Consecutive Integers from a Data Stream][2526] |![rs]
16521652
[2528][2528l]|[Maximize the Minimum Powered City][2528] |![rs]
16531653
[2529][2529l]|[Maximum Count of Positive Integer and Negative Integer][2529] |![py]
1654+
[2532][2532l]|[Time to Cross a Bridge][2532] |![rs]
16541655
[2535][2535l]|[Difference Between Element Sum and Digit Sum of an Array][2535] |![rs]
16551656
[2537][2537l]|[Count the Number of Good Subarrays][2537] |![rs]
16561657
[2540][2540l]|[Minimum Common Value][2540] |![rs]
@@ -3352,6 +3353,7 @@
33523353
[2526]:Problemset/2526-Find%20Consecutive%20Integers%20from%20a%20Data%20Stream/README.md#2526-find-consecutive-integers-from-a-data-stream
33533354
[2528]:Problemset/2528-Maximize%20the%20Minimum%20Powered%20City/README.md#2528-maximize-the-minimum-powered-city
33543355
[2529]:Problemset/2529-Maximum%20Count%20of%20Positive%20Integer%20and%20Negative%20Integer/README.md#2529-maximum-count-of-positive-integer-and-negative-integer
3356+
[2532]:Problemset/2532-Time%20to%20Cross%20a%20Bridge/README.md#2532-time-to-cross-a-bridge
33553357
[2535]:Problemset/2535-Difference%20Between%20Element%20Sum%20and%20Digit%20Sum%20of%20an%20Array/README.md#2535-difference-between-element-sum-and-digit-sum-of-an-array
33563358
[2537]:Problemset/2537-Count%20the%20Number%20of%20Good%20Subarrays/README.md#2537-count-the-number-of-good-subarrays
33573359
[2540]:Problemset/2540-Minimum%20Common%20Value/README.md#2540-minimum-common-value
@@ -5047,6 +5049,7 @@
50475049
[2526l]:https://leetcode.com/problems/find-consecutive-integers-from-a-data-stream/
50485050
[2528l]:https://leetcode.com/problems/maximize-the-minimum-powered-city/
50495051
[2529l]:https://leetcode.com/problems/maximum-count-of-positive-integer-and-negative-integer/
5052+
[2532l]:https://leetcode.com/problems/time-to-cross-a-bridge/
50505053
[2535l]:https://leetcode.com/problems/difference-between-element-sum-and-digit-sum-of-an-array/
50515054
[2537l]:https://leetcode.com/problems/count-the-number-of-good-subarrays/
50525055
[2540l]:https://leetcode.com/problems/minimum-common-value/

README_CN.md

+3
Original file line numberDiff line numberDiff line change
@@ -1651,6 +1651,7 @@
16511651
[2526][2526l]|[找到数据流中的连续整数][2526] |![rs]
16521652
[2528][2528l]|[最大化城市的最小电量][2528] |![rs]
16531653
[2529][2529l]|[正整数和负整数的最大计数][2529] |![py]
1654+
[2532][2532l]|[过桥的时间][2532] |![rs]
16541655
[2535][2535l]|[数组元素和与数字和的绝对差][2535] |![rs]
16551656
[2537][2537l]|[统计好子数组的数目][2537] |![rs]
16561657
[2540][2540l]|[最小公共值][2540] |![rs]
@@ -3352,6 +3353,7 @@
33523353
[2526]:Problemset/2526-Find%20Consecutive%20Integers%20from%20a%20Data%20Stream/README_CN.md#2526-找到数据流中的连续整数
33533354
[2528]:Problemset/2528-Maximize%20the%20Minimum%20Powered%20City/README_CN.md#2528-最大化城市的最小电量
33543355
[2529]:Problemset/2529-Maximum%20Count%20of%20Positive%20Integer%20and%20Negative%20Integer/README_CN.md#2529-正整数和负整数的最大计数
3356+
[2532]:Problemset/2532-Time%20to%20Cross%20a%20Bridge/README_CN.md#2532-过桥的时间
33553357
[2535]:Problemset/2535-Difference%20Between%20Element%20Sum%20and%20Digit%20Sum%20of%20an%20Array/README_CN.md#2535-数组元素和与数字和的绝对差
33563358
[2537]:Problemset/2537-Count%20the%20Number%20of%20Good%20Subarrays/README_CN.md#2537-统计好子数组的数目
33573359
[2540]:Problemset/2540-Minimum%20Common%20Value/README_CN.md#2540-最小公共值
@@ -5047,6 +5049,7 @@
50475049
[2526l]:https://leetcode.cn/problems/find-consecutive-integers-from-a-data-stream/
50485050
[2528l]:https://leetcode.cn/problems/maximize-the-minimum-powered-city/
50495051
[2529l]:https://leetcode.cn/problems/maximum-count-of-positive-integer-and-negative-integer/
5052+
[2532l]:https://leetcode.cn/problems/time-to-cross-a-bridge/
50505053
[2535l]:https://leetcode.cn/problems/difference-between-element-sum-and-digit-sum-of-an-array/
50515054
[2537l]:https://leetcode.cn/problems/count-the-number-of-good-subarrays/
50525055
[2540l]:https://leetcode.cn/problems/minimum-common-value/

0 commit comments

Comments
 (0)