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 个盒子都需要放入新仓库,请你返回最后一个搬运箱子的工人 到达河左岸 的时间。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/time-to-cross-a-bridge
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution {
public int findCrossingTime(int n, int k, int[][] time) {
// 定义等待中的工人优先级比较规则,时间总和越高,效率越低,优先级越低,越优先被取出
PriorityQueue<Integer> waitLeft = new PriorityQueue<Integer>((x, y) -> {
int timeX = time[x][0] + time[x][2];
int timeY = time[y][0] + time[y][2];
return timeX != timeY ? timeY - timeX : y - x;
});
PriorityQueue<Integer> waitRight = new PriorityQueue<Integer>((x, y) -> {
int timeX = time[x][0] + time[x][2];
int timeY = time[y][0] + time[y][2];
return timeX != timeY ? timeY - timeX : y - x;
});
PriorityQueue<int[]> workLeft = new PriorityQueue<int[]>((x, y) -> {
if (x[0] != y[0]) {
return x[0] - y[0];
} else {
return x[1] - y[1];
}
});
PriorityQueue<int[]> workRight = new PriorityQueue<int[]>((x, y) -> {
if (x[0] != y[0]) {
return x[0] - y[0];
} else {
return x[1] - y[1];
}
});
int remain = n, curTime = 0;
for (int i = 0; i < k; i++) {
waitLeft.offer(i);
}
while (remain > 0 || !workRight.isEmpty() || !waitRight.isEmpty()) {
// 1. 若 workLeft 或 workRight 中的工人完成工作,则将他们取出,并分别放置到 waitLeft 和 waitRight 中。
while (!workLeft.isEmpty() && workLeft.peek()[0] <= curTime) {
waitLeft.offer(workLeft.poll()[1]);
}
while (!workRight.isEmpty() && workRight.peek()[0] <= curTime) {
waitRight.offer(workRight.poll()[1]);
}
if (!waitRight.isEmpty()) {
// 2. 若右侧有工人在等待,则取出优先级最低的工人并过桥
int id = waitRight.poll();
curTime += time[id][2];
workLeft.offer(new int[]{curTime + time[id][3], id});
} else if (remain > 0 && !waitLeft.isEmpty()) {
// 3. 若右侧还有箱子,并且左侧有工人在等待,则取出优先级最低的工人并过桥
int id = waitLeft.poll();
curTime += time[id][0];
workRight.offer(new int[]{curTime + time[id][1], id});
remain--;
} else {
// 4. 否则,没有人需要过桥,时间过渡到 workLeft 和 workRight 中的最早完成时间
int nextTime = Integer.MAX_VALUE;
if (!workLeft.isEmpty()) {
nextTime = Math.min(nextTime, workLeft.peek()[0]);
}
if (!workRight.isEmpty()) {
nextTime = Math.min(nextTime, workRight.peek()[0]);
}
if (nextTime != Integer.MAX_VALUE) {
curTime = Math.max(nextTime, curTime);
}
}
}
return curTime;
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!