http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=103&page=show_problem&problem=481
题意:
输入几个队伍,各队列有其队员。接着输入进队出队指令,模拟队列,输出每次出队的队员号。
其中,该队列有以下特点:进队前,队列如a.1 - b.1 - c.1 - d.1;b.2进队时,接在自己队员后面,队列变成a.1 - b.1 - b.2 - c.1 - d.1,同理,其它队队员进队列也是一样的道理;出队时,如普通队列一样,队首出队。
解题:
研究了好久的题目啊。看了别人题解才搞定的。
一开始想用queue+vector来模拟解决,可发现queue/vector不能嵌套使用。
学习了网上的解决方法,自己用数组来模拟各队进队列的情况。
注意:
a. 在可能存在空行或回车的情况下,使用gets(char*)来消除更保证,用cin.ignore只能消一个字符,如果是多空格空行就解决不了了。
b. 虽然使用istringstream分离字符串、用int member = atoi(word.c_str())很方便;如果数据行结构已经很明确,一次使用sscanf(char*, "%s %d", str, &num)会更高效准确。
#include <iostream>
#include <list>
#include <map>
#include <string.h>
#include <sstream>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
#define LOCAL_TEST
const int NUMBER_TEAMS = 1000;
struct ltstr
{
bool operator()(const int a, const int b)const
{
return a < b;
}
};
map <int,int, ltstr> mapTeammates;
int szTeammates[NUMBER_TEAMS][2000];
int szIndexQueueFront[NUMBER_TEAMS];
int szIndexQueueBack[NUMBER_TEAMS];
int TeamsQueue[NUMBER_TEAMS];
int TeamsFront;
int TeamsBack;
// use to count whether the team is visited
int TeamsVis[NUMBER_TEAMS];
void Init()
{
mapTeammates.clear();
memset(szTeammates, 0, NUMBER_TEAMS * 2000);
memset(szIndexQueueFront, 0, NUMBER_TEAMS);
memset(szIndexQueueBack, -1, NUMBER_TEAMS);
memset(TeamsQueue, 0, NUMBER_TEAMS);
TeamsFront = 0;
TeamsBack = -1;
memset(TeamsVis, 0, NUMBER_TEAMS);
}
void Enqueue(int member)
{
// Get the member's TeamNumber
int iTeamnumber = mapTeammates[member];
// if the team hasn't been visited
if ( TeamsVis[iTeamnumber] == 0 )
{
TeamsVis[iTeamnumber] = 1;
TeamsQueue[++TeamsBack] = iTeamnumber;
} // end if
// Corresponding BackNumber plus 1, and set member into the team
szTeammates[iTeamnumber][++szIndexQueueBack[iTeamnumber]] = member;
}
void Dequeue()
{
// if TeamQueue is not empty
if ( TeamsFront <= TeamsBack )
{
int iTeamnumber = TeamsQueue[TeamsFront];
int iFront = szIndexQueueFront[iTeamnumber];
int iBack = szIndexQueueBack[iTeamnumber];
// In "Teams of iTeamnumber", if front <= back, in other words, list is no empty
if ( szIndexQueueFront[iTeamnumber] <= szIndexQueueBack[iTeamnumber] )
{
cout <<szTeammates[iTeamnumber][szIndexQueueFront[iTeamnumber]];
cout <<'\n';
szIndexQueueFront[iTeamnumber]++;
// if list becomes empty
if ( szIndexQueueFront[iTeamnumber] > szIndexQueueBack[iTeamnumber] )
{
// Remove this iTeamnumber
TeamsFront++;
TeamsVis[iTeamnumber] = 0;
} // end if
} // end if
} // end if
}
void PrintOut()
{
if ( TeamsFront <= TeamsBack )
for ( int i=TeamsFront; i<=TeamsBack; i++ )
for ( int k=szIndexQueueFront[i]; k<=szIndexQueueBack[i]; k++ )
{
cout <<szTeammates[i][k];
cout <<'\n';
} // end for
}
int main()
{
#ifdef LOCAL_TEST
freopen("f:\\in.txt", "r", stdin);
freopen("f:\\out.txt", "w+", stdout);
#endif
int nCase = 0;
while ( 1 )
{
// Get the number of teams
int numberOfTeams;
cin >>numberOfTeams;
if ( numberOfTeams == 0 )
break;
// Initialize map and arrays
Init();
nCase++;
// Get the teammates
for ( int i=0; i<numberOfTeams; i++ )
{
int numberOfTeammates;
int member;
cin >>numberOfTeammates;
for ( int k=0; k<numberOfTeammates; k++ )
{
cin >>member;
mapTeammates.insert(make_pair(member, i));
} // end for
} // end for
cout <<"Scenario #" <<nCase <<'\n';
// Get inputCode and process
char temp[50];
// erase blank line(which may contain several blank spaces)
gets(temp);
while ( gets(temp) )
{
string strWords(temp);
string word;
istringstream strStream(strWords);
strStream >>word;
if ( word == "STOP" )
{
cout <<"\n";
break;
} // end if
else
if ( word == "DEQUEUE" )
Dequeue();
else
{
// OK version - 1
// int num;
// char cmd[20];
// sscanf(temp, "%s %d", cmd, &num);
// Enqueue(num);
// OK version - 2
strStream >>word;
int member = atoi(word.c_str());
Enqueue(member);
}
} // end while
} // end while
return 0;
}