|
| 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 | +``` |
0 commit comments