有t个团体的人正在排一个长队。每次新来一个人时,如果这个成员所在的团体已经有人在排队了,那么他就加到最后一个队友身后;如果整个大队列中没有他的团体,那么他就要排在整个大队列的最后。
输入每个团队的人数,每个人的编号,要求支持下面的操作(前两种操作可以交叉进行):
ENQUEUE x:编号x的人进入长队;
DEQUEUE: 长队的队首出队,并输出出队人的编号;
STOP:停止模拟
Key:设置两个队列: 储存长队中团队的先后顺序,每个团队内部成员的顺序
#include <cstdio>
#include <queue>
#include <map>
using namespace std;
const int maxt=1005;
int main(){
int t,kase=0; //团队数
while(scanf("%d",&t)==1&&t){
printf("Scenario #%d\n",++kase);
map<int,int>team; //用于将人员编号与队伍编号一一对应
for(int i=1;i<=t;i++){ //输入编号
int n,x; //n为每一队的人
scanf("%d",&n);
while(n--){
scanf("%d",&x);
team[x]=i;
}
}
queue<int>total,perTeam[maxt]; //total是整个队伍(里面是队伍编号),perTeam是单个队伍
for(;;){
char cmd[10];
scanf("%s",cmd);
if(cmd[0]=='S') break; //注意 if, else if, else if; 不是 if, if,else
else if(cmd[0]=='E'){
int x;
scanf("%d",&x);
int ID=team[x];
if(perTeam[ID].empty()){ //为空,则该团队中没有人在整个队伍中
total.push(ID);
perTeam[ID].push(x);
}
else perTeam[ID].push(x);
}
else if(cmd[0]=='D'){
int ID=total.front();
int topID=perTeam[ID].front();
perTeam[ID].pop();
if(perTeam[ID].empty()) total.pop(); //如果这个团队在整体队伍中无人了,团队编号出队
printf("%d\n",topID);
}
}
}
return 0;
}
注意点:1.queuetotal,perTeam[maxt]; 队列和队列数组可以同时声明。
2.for(;;) for也可以用于不确定次数的循环,而且相较于while,适用于那些不大好将条件分离出来的循环。
3.//注意 if, else if, else if; 不是 if, if,else 。因为cmd不止只有合法的三种,还有其他不合法的命令,应该不予理会。
4.cmd:学习命令的输入和判别。
5.queue.pop()返回为void。
5.有些代码可以简化:
1)分支结构中有相同操作的:
else if(cmd[0]=='E'){
int x;
scanf("%d",&x);
int ID=team[x];
if(perTeam[ID].empty()){
total.push(ID);
perTeam[ID].push(x);
}
else perTeam[ID].push(x);
}
变为:
else if(cmd[0]=='E'){
int x;
scanf("%d",&x);
int ID=team[x];
if(perTeam[ID].empty()) total.push(ID);
perTeam[ID].push(x);
}
2)去掉一些变量的定义:
else if(cmd[0]=='D'){
int ID=total.front();
int topID=perTeam[ID].front();
perTeam[ID].pop();
if(perTeam[ID].empty()) total.pop();
printf("%d\n",topID);
}
变为:
else if(cmd[0]=='D'){
int ID=total.front();
printf("%d\n",topID=perTeam[ID].front());
perTeam[ID].pop();
if(perTeam[ID].empty()) total.pop();
}