C# 代码
public class Solution {
// 根据规则可以整理出以下内容:
// 1.桥上只能有一个人通过
// 2.右侧优先过桥
// 3.效率低的工人优先过桥
// 4.桥上没人,右侧没人,旧仓库有箱子,左边才可以过桥
public int FindCrossingTime(int n, int k, int[][] time) {
int result = 0;
// 根据规则3,优先将time数组排序,优先派出效率低的工人
// Array.Sort血坑, Linq yyds
time = time.OrderByDescending(t => t[0] + t[2]).ThenByDescending(t => Array.IndexOf(time, t)).ToArray();
// work: 操作箱子, wait: 桥边等待
// 队列中需要记录当前工人的下标和当前的时间
PriorityQueue<int[], int> leftWork = new PriorityQueue<int[], int>();
PriorityQueue<int[], int> rightWork = new PriorityQueue<int[], int>();
PriorityQueue<int[], int> leftWait = new PriorityQueue<int[], int>();
PriorityQueue<int[], int> rightWait = new PriorityQueue<int[], int>();
// 初始化, 所有工人在左侧等待
for (int i = 0; i < k; i++){
leftWait.Enqueue(new int[2] {i, 0}, i);
}
while (n > 0){
// 不同工人可以同时放下所选的箱子, 只要工人的时间没有超出当前时间都可以操作箱子
while (leftWork.Count > 0 && leftWork.Peek()[1] <= result){
int[] t = leftWork.Dequeue();
leftWait.Enqueue(t, t[0]);
}
while (rightWork.Count > 0 && rightWork.Peek()[1] <= result){
int[] t = rightWork.Dequeue();
rightWait.Enqueue(t, t[0]);
}
// 根据规则2, 优先处理右侧有人等待
if (rightWait.Count > 0){
int[] t = rightWait.Dequeue();
result += time[t[0]][2];
t[1] = result + time[t[0]][3];
leftWork.Enqueue(t, t[1]);
}
else{
// 根据规则4, 右侧无人等待, 左侧可以过桥
if (leftWait.Count > 0){
int[] t = leftWait.Dequeue();
result += time[t[0]][0];
t[1] = result + time[t[0]][1];
// 右侧操作队列加入元素, 表示有一个旧箱子处理过, n减一
rightWork.Enqueue(t, t[1]);
n--;
}
else{
// 左右两侧都没有人等待, 并且操作箱子的时间大于result, 将时间更新
if (leftWork.Count > 0 && rightWork.Count > 0){
result = Math.Min(leftWork.Peek()[1], rightWork.Peek()[1]);
}
else if (leftWork.Count > 0){
result = leftWork.Peek()[1];
}
else if (rightWork.Count > 0){
result = rightWork.Peek()[1];
}
}
}
}
// 所有箱子都已经操作过, 如果右侧队列中还有元素, 更新时间
// 答案统计最后一个搬运箱子的工人到达河左岸的时间, 不需要再加入leftWait
// 也不需要加入rightWait, 直接使用time[i][2]进行计算
while (rightWork.Count > 0){
int[] t = rightWork.Dequeue();
if (t[1] > result){
result = t[1];
}
result += time[t[0]][2];
}
return result;
}
}