转载:https://www.cnblogs.com/yjlblog/p/7056746.html 作者:YJLAugus
题目:《算法竞赛入门经典》 刘汝佳 5-6 团体队列 P117
题目背景
队列和优先级队列是大多数计算机科学家都知道的
数据结构
。但是团队队列却不被人熟知,尽管在生活中经常出现。比如,午餐时间的食堂门口的队列就是一个团队队列。在一个团队队列中,每个元素属于一个团队。如果一个元素进入一个队列,它首先从头到尾地搜寻这个队列——检查是否它的队友(在同一个团队称之为队友)也在这个队列里。如果有,它就排在它队友的后面(:-D就是插队咯~~)。如果没有,它就排在整个队列的最后,成为新的最后一名(/(ㄒoㄒ)/~真是不幸)。在普通队列中出队是这样的:元素从头到尾的被处理,按他们出现在团队队列里的顺序。你的任务是写一个程序模拟这样一个团队队列。
输入
输入文件会包含一个或多个测试样例。每一个测试样例由代表团队数量的t(1<=t<=1000)开始。然后t只团队描述如下,每一个团队由一个表示元素个数的数字,以及每个元素组成。元素属于整型,并且范围在0到999999(一百万减一)之间。一个团队可能有多达1000个元素。最后,指令列表如下。有三种不同的指令:ENQUEUE x——x进入团队队列。DEQUEUE x——处理第一个元素并将其移除STOP——结束一个测试样例。当t是0时,输入终止。警告:一个测试样例可能多达200000(/(ㄒoㄒ)/~~二十万)条指令,所以团队队列的实现应该是有效率的:入队和出队都应该花费常数时间。
输出
对应每个测试样例,首先输出一行“Scenario #k”,其中k表示第几次测试。然后,每一个“DEQUEUE”指令打印包含出队的元素(单独占一行)。打印一空行在每一个测试样例之后,即使是最后一个测试样例。
例如:Sample Input
2
3 101 102 103
3 201 202 203
ENQUEUE 101
ENQUEUE 201
ENQUEUE 102
ENQUEUE 202
ENQUEUE 103
ENQUEUE 203
DEQUEUE
DEQUEUE
DEQUEUE
DEQUEUE
DEQUEUE
DEQUEUE
STOP
2
5
259001 259002 259003 259004 259005
6 260001 260002 260003 260004 260005
260006
ENQUEUE 259001
ENQUEUE 260001
ENQUEUE 259002
ENQUEUE
259003
ENQUEUE 259004
ENQUEUE 259005
DEQUEUE
DEQUEUE
ENQUEUE
260002
ENQUEUE
260003
DEQUEUE
DEQUEUE
DEQUEUE
DEQUEUE
STOP
0
Sample Output
Scenario
#1
101
102
103
201
202
203
Scenario
#2
259001
259002
259003
259004
259005
260001
分析
题目明确告诉了我们使用队列。使用一个队列排列团队;再使用一个队列排列元素。题目中说了出队入队只能花费常数时间,所以要在元素和团队之间建立映射关系而不能简单地使用数组存下元素。
代码
#include<iostream>
#include<map>
#include<queue>
#include<string>
using namespace std;
const int maxt=1000+10;
int main()
{
int t,i,j,kase=0;
int n,x;
string com;
while(cin>>t&&t)
{
cout<<"#"<<++kase<<endl;
map<int,int>team;
for(i=0;i<t;i++)//人为的0,1,2....队
{
cin>>n;
for(j=0;j<n;j++)
{
cin>>x;
team[x]=i;//将每个小队的人和对建立映射
}
}
getchar();//接收上面的回车
queue<int>q,q2[maxt];
while(1)
{
cin>>com;
if(com[0]=='S')
break;
else if(com[0]=='E')
{
cin>>x;
t=team[x];
if(q2[t].empty())//如果所在小队没有人,就只能插在大队的队尾
q.push(t); //怎么插呢,把你们队的编号(队旗)插在那里就好
//要是把自己插进去也行,代码稍稍改变下就好
q2[t].push(x);
}
else if(com[0]=='D')
{
if(q.empty())
cout<<"There are no persons.\n";
else
{
t=q.front();
cout<<q2[t].front()<<endl;
q2[t].pop();
if(q2[t].empty())
q.pop();
}
}
}
}
return 0;
}
小结
push()会将一个元素置入queue中。
- front()会返回queue内的第一个元素(也就是第一个被置入的元素)。
- back()会返回queue中最后一个元素(也就是最后被插入的元素)。
- top()取队首元素(但不删除)。
- pop()会从queue中移除一个元素。
- 注意:pop()虽然会移除下一个元素,但是并不返回它,front()和back()返回下一个元素但并不移除该元素。
补充:
2号队旗 |
1号队旗 | 0号队旗 |
201 | 202 | 205 | 206 |
105 | 101 |
003 |