原题:https://leetcode.cn/problems/time-to-cross-a-bridge/description/
class Solution {
typedef pair<int, int> PII;
public:
int findCrossingTime(int n, int k, vector<vector<int>>& time) {
/**
四个堆结构
wait_l: 效率低优先(下标大), 维护工人下标(可表示效率)和到达桥的时间
work_l: 完成时间小优先,维护完成时间和工人下标
如果桥上有人在过桥,其他工人不能过桥要等待,curTime+=过桥所需时间后即可过桥
**/
//下标越大,效率越低
stable_sort(time.begin(), time.end(), [&](auto &va, auto &vb){
return va[0] + va[2] < vb[0] + vb[2];
});
priority_queue<PII> wait_l, wait_r;
priority_queue<PII, vector<PII>, greater<PII> > work_l, work_r;
for(int i = k - 1; i >= 0; i--)
wait_l.push({i, 0});
int curTime = 0;
while(n){
if(wait_r.size()){
auto [i, t] = wait_r.top();
wait_r.pop();
curTime += time[i][2];
work_l.push({curTime + time[i][3], i});
// cout << "r->l: " << i << " curTime: " << curTime << endl;
}else if(wait_l.size()){
auto [i, t] = wait_l.top();
wait_l.pop();
curTime += time[i][0];
// cout << "l->r: " << i << " curTime: " << curTime << endl;
work_r.push({curTime + time[i][1], i});
n--;//只要从左边过去右边一个人,n就要--了。以免左边多过桥的人拖慢总时间
}//一次过一个人
//如果工人搬东西的时间太长,一直在work,而等待过桥的人已经没了,curTime将会卡住
//需要将curTime更新到最快一个工人work完到wait到时间
else if (work_l.empty()) curTime = work_r.top().first;
else if (work_r.empty()) curTime = work_l.top().first;
else curTime = min(work_l.top().first, work_r.top().first);
// cout << "work_r.size(): " << work_r.size() << endl;
// cout << "work_r.top().first: " << work_r.top().first << endl;
// cout << "curTime: " << curTime << endl;
while(work_r.size() && work_r.top().first <= curTime){
auto [t, i] = work_r.top();
work_r.pop();
wait_r.push({i, t});
// cout << "old: " << i << " curTime: " << curTime << endl;
}
while(work_l.size() && work_l.top().first <= curTime){
auto [t, i] = work_l.top();
work_l.pop();
wait_l.push({i, t});
// cout << "new: " << i << " curTime: " << curTime << endl;
}
}
//最后箱子已经搬完,还剩下一批右边的人,最后一个过桥人的时间即为答案(最后不用考虑过桥顺序,答案相同)
//此时curTime可能 < t
while(wait_r.size()){
auto [i, t] = wait_r.top();
wait_r.pop();
curTime += time[i][2];
}
while(work_r.size()){
auto [t, i] = work_r.top();
work_r.pop();
curTime = max(t, curTime) + time[i][2];
}
return curTime;
}
};
更好的写法是改变while(n)中的顺序,过桥之后立刻判断n,右边的人全在work_r中,则最后可以不需要while(wait_r.size())的循环
class Solution {
typedef pair<int, int> PII;
public:
int findCrossingTime(int n, int k, vector<vector<int>>& time) {
/**
四个堆结构
wait_l: 效率低优先(下标大), 维护工人下标(可表示效率)和到达桥的时间
work_l: 完成时间小优先,维护完成时间和工人下标
如果桥上有人在过桥,其他工人不能过桥要等待,curTime+=过桥所需时间后即可过桥
**/
//下标越大,效率越低
stable_sort(time.begin(), time.end(), [&](auto &va, auto &vb){
return va[0] + va[2] < vb[0] + vb[2];
});
priority_queue<PII> wait_l, wait_r;
priority_queue<PII, vector<PII>, greater<PII> > work_l, work_r;
for(int i = k - 1; i >= 0; i--)
wait_l.push({i, 0});
int curTime = 0;
while(n){
while(work_r.size() && work_r.top().first <= curTime){
auto [t, i] = work_r.top();
work_r.pop();
wait_r.push({i, t});
// cout << "old: " << i << " curTime: " << curTime << endl;
}
while(work_l.size() && work_l.top().first <= curTime){
auto [t, i] = work_l.top();
work_l.pop();
wait_l.push({i, t});
// cout << "new: " << i << " curTime: " << curTime << endl;
}
if(wait_r.size()){
auto [i, t] = wait_r.top();
wait_r.pop();
curTime += time[i][2];
work_l.push({curTime + time[i][3], i});
// cout << "r->l: " << i << " curTime: " << curTime << endl;
}else if(wait_l.size()){
auto [i, t] = wait_l.top();
wait_l.pop();
curTime += time[i][0];
// cout << "l->r: " << i << " curTime: " << curTime << endl;
work_r.push({curTime + time[i][1], i});
n--;//只要从左边过去右边一个人,n就要--了。以免左边多过桥的人拖慢总时间
}//一次过一个人
//如果工人搬东西的时间太长,一直在work,而等待过桥的人已经没了,curTime将会卡住
//需要将curTime更新到最快一个工人work完到wait到时间
else if (work_l.empty()) curTime = work_r.top().first;
else if (work_r.empty()) curTime = work_l.top().first;
else curTime = min(work_l.top().first, work_r.top().first);
// cout << "work_r.size(): " << work_r.size() << endl;
// cout << "work_r.top().first: " << work_r.top().first << endl;
// cout << "curTime: " << curTime << endl;
}
//最后箱子已经搬完,还剩下一批右边的人,最后一个过桥人的时间即为答案(最后不用考虑过桥顺序,答案相同)
//此时curTime可能 < t
// while(wait_r.size()){
// auto [i, t] = wait_r.top();
// wait_r.pop();
// curTime += time[i][2];
// }
while(work_r.size()){
auto [t, i] = work_r.top();
work_r.pop();
curTime = max(t, curTime) + time[i][2];
}
return curTime;
}
};