题目链接: http://poj.org/problem?id=2259
题目大意:
告诉你一堆人(m个人是一组的,n个人是一组的。。。。);然后一个人来排队了,先看下有自己组的熟人吗?有的话直接排在自己组的人的队尾(呵呵,是不是现实中有这样的),没有熟人的话直接排队尾咯。 题目给定进队和出队命令,求解出队的顺序。
思路:
- 每个组需要有一个队列
queue<int> team[teamIndex]
- 每个组需要一个标记,我们组是否有人 true,false
bool teamInQueue[teamIndex]
- 每个人与组号之间的映射
people[peopleID]=teamIndex
- 如果组的标记为 true,再把组的序号存成大的队列
queue<int> mainQueue
- 入队:检查人ID是哪个组的;check组号的标记,知道组是否在大队 mainQueue里,true,则在该组入队,false,则把自己组的标记改成 true,并把自己的组号压入大队 mainQueue里,并且自己入队该组
- 出队:找到 mainQueue里的 front是哪个组的组号,从该组打印ID并出队;检查该组还有人吗,如果没人了,把该组组号从 mainQueue里出队,并把该组的标记改成false
Accepted 代码如下:
代码语言:javascript复制/**
* @description: poj2259 团队排队问题
* @author: michael ming
* @date: 2019/4/5 11:24
* @modified by:
*/
#include <iostream>
#include <queue>
#include <string>
using namespace std;
#define MAX 1000
#define MAX_PEOPLE 1000000
queue<int> team[MAX]; //team[i]代表一个组队列
queue<int> mainQueue; //宏观主队列,存储teamIndex值
bool teamInQueue[MAX]; //队伍是否排在主队列中
int people[MAX_PEOPLE]; //存储人的队伍teamIndex编号
int teamNums, Scenario=1;
void init() //每次进入下一次任务时,清空前一次的记录
{
for(int i = 0; i < teamNums; i) //队列清空
{
teamInQueue[i] = false;
while(!team[i].empty())
team[i].pop();
}
while(!mainQueue.empty())
mainQueue.pop();
}
void input() //输入人员信息,及记录每人的组号
{
int totalPeopleInTeam,peopleID;
for(int teamIndex = 0; teamIndex < teamNums; teamIndex)
{
cin >> totalPeopleInTeam;
for(int j = 0; j < totalPeopleInTeam; j)
{
cin >> peopleID;
people[peopleID] = teamIndex;
//把每个人的ID(数组中的位置)与其值(组号)建立映射
}
}
}
void solve()
{
int peopleID,teamID;
string command;
cout << "Scenario #" << Scenario << endl;
while(cin >> command && command[0] != 'S') //STOP停止
{
if (command[0] == 'E') //ENQUEUE入队
{
cin >> peopleID; //输入ID后查询其组号teamID(即people[peopleID])
teamID = people[peopleID];
if(teamInQueue[teamID]) //组号是否在大队列里呢(初始为false不在)
{
team[teamID].push(peopleID); //找到我的组入组
}
else //我组没人,我是第一个
{
teamInQueue[teamID] = true; //我们组终于有人了
mainQueue.push(teamID); //我们组的组号排在最后一组
team[teamID].push(peopleID); //找到我的组入组
}
}
else //DEQUEUE出队
{
if(!mainQueue.empty()) //大团组必须还有,如果无,则完全没人了
{
teamID = mainQueue.front(); //队头是哪个组的呀
cout << team[teamID].front() << endl; //从相应的组里找到该组的头
team[teamID].pop(); //打印了,出队
if(team[teamID].empty()) //这个组空了,都出去了
{
teamInQueue[teamID] = false; //标记一下
mainQueue.pop(); //从大队里删除空组
}
}
}
}
cout << endl;
}
int main()
{
while(cin >> teamNums && teamNums)
{
init(); //初始化组的标记,及清空队列
input(); //输入人员ID,记录人员组号
solve(); //队列出队,入队操作
}
return 0;
}