原题链接:UVa 10901: Ferry Loading III
题目大意:使用渡船运输汽车,给定渡船的最大载车数n、渡河所需时间t(来去时间相同)。只要河两岸有车在等待运输,船就进入工作状态,将船运至对岸。超出载量的车就等下次船靠岸的时候再进行运输,船初始停靠在左岸。若船靠岸时没有车处于等待运输状态,则船停留直到两岸之一有车抵达。需要注意的是,若船停靠在左岸,但右岸比左岸先有车来,则船要空着开到右岸去运输右岸的车,反之亦然。
大致思路:有车来,船就进入工作状态,没车来就等到有车来。
#include <climits>
#include <string>
#include <iostream>
#include <queue>
using namespace std;
#define MAXM 10000
int event[MAXM];
bool side[MAXM];
int times[MAXM];
int main() {
int c, n, t, m;
cin >> c;
while(c--) {
cin >> n >> t >> m;
for(int i = 0; i < m; i++) {
string si;
cin >> event[i] >> si;
side[i] = si == "left";
}
queue<int> left, right, inBoat;
bool inLeft = true;
int arrivalTime = INT_MAX;
int currEv = 0;
while(currEv < m || arrivalTime != INT_MAX) {
if(currEv != m && event[currEv] <= arrivalTime) {
(side[currEv] ? left : right).push(currEv);
if(arrivalTime == INT_MAX) arrivalTime = event[currEv];
currEv++;
} else {
while(!inBoat.empty()) {
times[inBoat.front()] = arrivalTime;
inBoat.pop();
}
if(left.empty() && right.empty()) {
arrivalTime = INT_MAX;
} else {
queue<int>& curr = inLeft ? left : right;
while(!curr.empty() && (int) inBoat.size() < n) {
inBoat.push(curr.front());
curr.pop();
}
arrivalTime = arrivalTime + t;
inLeft = !inLeft;
}
}
}
for(int i = 0; i < m; i++) cout << times[i] << endl;
if(c) cout << endl;
}
return 0;
}
代码分析: 使用三个数组分别存放:汽车抵达时间、抵达哪一边、最终到达对岸的时间。再用三个队列分别存放:左岸处于等待状态的汽车、右岸处于等待状态的汽车、处于运输状态的汽车。当船处于初始状态或空闲状态时,抵达时间arrivalTime都为INT_MAX,直到有车来再将其置为该车的抵达时间。状态变量inLeft用于判断当前船在左边还是右边。另外,37-46行代码为关键部分,意思是:若没有车处于等待状态,则船靠在当前岸等待;若有车在等,则不论当前停靠的岸上有没有车,船都要过河(若有车,则要运输,要过河;若无车,则对面有车在等,还是要过河)。