2023-07-07每日一题
一、题目编号
2532. 过桥的时间
二、题目链接
点击跳转到题目位置
三、题目描述
共有 k 位工人计划将 n 个箱子从旧仓库移动到新仓库。给你两个整数 n 和 k,以及一个二维整数数组 time ,数组的大小为 k x 4 ,其中 time[i] = [leftToRighti, pickOldi, rightToLefti, putNewi] 。
一条河将两座仓库分隔,只能通过一座桥通行。旧仓库位于河的右岸,新仓库在河的左岸。开始时,所有 k 位工人都在桥的左侧等待。为了移动这些箱子,第 i 位工人(下标从 0 开始)可以:
- 从左岸(新仓库)跨过桥到右岸(旧仓库),用时 leftToRighti 分钟。
- 从旧仓库选择一个箱子,并返回到桥边,用时 pickOldi 分钟。不同工人可以同时搬起所选的箱子。
- 从右岸(旧仓库)跨过桥到左岸(新仓库),用时 rightToLefti 分钟。
- 将箱子放入新仓库,并返回到桥边,用时 putNewi 分钟。不同工人可以同时放下所选的箱子。
如果满足下面任一条件,则认为工人 i 的 效率低于 工人 j :
- leftToRighti + rightToLefti > leftToRightj + rightToLeftj
- leftToRighti + rightToLefti == leftToRightj + rightToLeftj 且 i > j
工人通过桥时需要遵循以下规则:
- 如果工人 x 到达桥边时,工人 y 正在过桥,那么工人 x 需要在桥边等待。
- 如果没有正在过桥的工人,那么在桥右边等待的工人可以先过桥。如果同时有多个工人在右边等待,那么 效率最低 的工人会先过桥。
- 如果没有正在过桥的工人,且桥右边也没有在等待的工人,同时旧仓库还剩下至少一个箱子需要搬运,此时在桥左边的工人可以过桥。如果同时有多个工人在左边等待,那么 效率最低 的工人会先过桥。
所有 n 个盒子都需要放入新仓库,请你返回最后一个搬运箱子的工人 到达河左岸 的时间。
提示:文章来源:https://www.toymoban.com/news/detail-555870.html
- 1 <= n, k <= 104
- time.length == k
- time[i].length == 4
- 1 <= leftToRighti, pickOldi, rightToLefti, putNewi <= 1000
四、解题代码
/*
time[i][0] : leftToRight
time[i][1] : pickOld
time[i][2] : rightToLeft
time[i][3] : putNew
*/
class Solution {
public:
using p = pair<int, int>;
int findCrossingTime(int n, int k, vector<vector<int>>& time) {
auto wait_priority_cmp = [&](int x, int y) {
int time_x = time[x][0] + time[x][2];
int time_y = time[y][0] + time[y][2];
return time_x != time_y ? time_x < time_y : x < y;
};
/*
优先队列1 左右等待
*/
priority_queue<int, vector<int>, decltype(wait_priority_cmp)> wait_left(wait_priority_cmp),
wait_right(wait_priority_cmp);
/*
优先队列2 左右工作
*/
priority_queue<p, vector<p>, greater<p>> work_left, work_right;
int remain_box = n, cur_time = 0;
for(int i = 0; i < k; ++i){
wait_left.push(i);
}
while(remain_box > 0 || !work_right.empty() || !wait_right.empty()){
while (!work_left.empty() && work_left.top().first <= cur_time) {
wait_left.push(work_left.top().second);
work_left.pop();
}
while (!work_right.empty() && work_right.top().first <= cur_time) {
wait_right.push(work_right.top().second);
work_right.pop();
}
if (!wait_right.empty()) {
// 2. 若右侧有工人在等待,则取出优先级最低的工人并过桥
int id = wait_right.top();
wait_right.pop();
cur_time += time[id][2];
work_left.push({cur_time + time[id][3], id});
} else if (remain_box > 0 && !wait_left.empty()) {
// 3. 若右侧还有箱子,并且左侧有工人在等待,则取出优先级最低的工人并过桥
int id = wait_left.top();
wait_left.pop();
cur_time += time[id][0];
work_right.push({cur_time + time[id][1], id});
remain_box--;
} else {
// 4. 否则,没有人需要过桥,时间过渡到 work_left 和 work_right 中的最早完成时间
int next_time = INT_MAX;
if (!work_left.empty()) {
next_time = min(next_time, work_left.top().first);
}
if (!work_right.empty()) {
next_time = min(next_time, work_right.top().first);
}
if (next_time != INT_MAX) {
cur_time = max(next_time, cur_time);
}
}
}
return cur_time;
}
};
五、解题思路
(1) 采用优先队列进行模拟。文章来源地址https://www.toymoban.com/news/detail-555870.html
到了这里,关于2023-07-07 LeetCode每日一题(过桥的时间)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!