Time to Cross a Bridge (2532) ⧉
This problem, which featured as the Hard in LeetCode Weekly 327, describes a situation in which some number of workers need to transfer boxes from one warehouse across a bridge to another. We are required to implement a function that returns the time it takes to transfer all boxes from the old warehouse across the bridge to the new warehouse.
This is a classic simulation exercise. The crux of the problem is this:
- Read the rules
- Read the rules again, carefully
- Efficiently simulate the situation
Turns out a priority queue is pretty great way to simulate a strictly-prioritized queue!
_86class Solution {_86 public:_86 static int findCrossingTime(int n, int k, vector<vector<int>> &time) {_86 const auto left_to_right = [&time] (int worker) { return time[worker][0]; };_86 const auto pick_up_box = [&time] (int worker) { return time[worker][1]; };_86 const auto right_to_left = [&time] (int worker) { return time[worker][2]; };_86 const auto put_down_box = [&time] (int worker) { return time[worker][3]; };_86_86 vector<int> efficiency(k);_86 vector<int> time_free(k, INT_MAX);_86_86 for (int i = 0; i < k; ++i) {_86 efficiency[i] = left_to_right(i) + right_to_left(i);_86 }_86_86 auto least_efficient = [&efficiency](int a, int b) {_86 if (efficiency[a]==efficiency[b]) { return a < b; }_86 return efficiency[a] < efficiency[b];_86 };_86_86 auto first_free = [&time_free](int a, int b) {_86 return time_free[a] > time_free[b];_86 };_86_86 priority_queue<int, vector<int>, decltype(least_efficient)> left(least_efficient), right(least_efficient);_86 priority_queue<int, vector<int>, decltype(first_free)> done_on_left(first_free), done_on_right(first_free);_86_86 for (int i = 0; i < k; ++i)_86 left.push(i);_86_86 int boxes_left = n;_86 int current_time = 0;_86_86 while (boxes_left > 0 || not right.empty() || not done_on_right.empty()) {_86_86 // prefer crossing right to left_86 if (not right.empty()) {_86 int worker = right.top();_86 right.pop();_86_86 current_time += right_to_left(worker);_86_86 // this worker will be ready to rejoin the left queue_86 time_free[worker] = current_time + put_down_box(worker);_86 done_on_left.push(worker);_86_86 } else if (not left.empty() && boxes_left > 0) {_86_86 int worker = left.top();_86 left.pop();_86_86 // this worker "claims" a box_86 boxes_left -= 1;_86_86 current_time += left_to_right(worker);_86_86 // this worker will be ready to rejoin the right queue_86 time_free[worker] = current_time + pick_up_box(worker);_86 done_on_right.push(worker);_86_86 } else {_86 current_time = min(_86 done_on_right.empty() ? INT_MAX : time_free[done_on_right.top()],_86 done_on_left.empty() ? INT_MAX : time_free[done_on_left.top()]_86 );_86 }_86_86 // let any workers who are done rejoin the respective queues_86 while (not done_on_right.empty() && time_free[done_on_right.top()] <= current_time) {_86 int worker = done_on_right.top();_86 done_on_right.pop();_86_86 right.push(worker);_86 }_86_86 while (not done_on_left.empty() && time_free[done_on_left.top()] <= current_time) {_86 int worker = done_on_left.top();_86 done_on_left.pop();_86_86 left.push(worker);_86 }_86 }_86_86 return current_time;_86 }_86};
If you found this solution helpful, consider leaving a star!