《算法竞赛入门经典2ndEdition 》例题5-6 团体队列(Team Queue, Uva540)

   先来说说自己对这道题的领悟。
   首先,这题使用STL的思路我通过自己的思考能够想到我觉得后面的实现其实不成问题(个人想了很久才想到这样使用STL,第一开始还以为得直接用list呢),然而过程中还是发现了许多问题,下面我就来说说。
   通过这道题还是学会了不少,不过即使现在做对了,仍然不知道自己之前这个为什么使用`vector< queue<int> > q;` 会无法编译通过,如果有大神出没,求解答,万分感激。
   另外呢,这道题对于时间有要求,如果使用`cin cout 等等` 就会TLE,都换成`scanf printf` 一下子时间消耗就降低了。
   还有,这道题题目描述最后说了

Print a blank line after each test case, even after the last one.

   可是我并没有注意到,还傻傻的把最后一个空行删掉了,导致在改完TLE之后成了WA。

   接下来说说这道题的思路吧,就是因为每个team在大队列中都可以看作一个小队列(大队列中的夹个也就是插入某个小队列的末尾),用关联数组将每个team赋予一个编号,大队列中只存储队列中现有team的编号,利用一个队列的数组来存放每个team的小队列,可以直接通过数组下标来访问这个小队列。
   下面就是代码。
#include <cstdio>
#include <iostream>
#include <map>
#include <vector>
#include <queue>
using namespace std;

map<int, int> team;//某个人对应这个人所在队伍的编号
//vector< queue<int> > q;//保存每个队伍的小队列
queue<int> q[1010];//保存每个队伍的小队列
queue<int> qt;//在大队列中每个队伍的序号保存在此队列中
int main()
{
  freopen("New Text Document.txt","r",stdin);
  freopen("Output.txt","w",stdout);
  //ios::sync_with_stdio(false);
  int t, kase = 0;
  char s[30];
  while(scanf("%d", &t) != EOF)
  {
    if(!t) break;
    printf("Scenario #%d\n", ++kase);
    team.clear();
    for(int i = 0; i < 1000; i++)
    while(!q[i].empty()) q[i].pop();
    //q.clear(); 
    while(!qt.empty()) qt.pop();
    for(int i = 0; i < t; i++)
    {
      int j, x;
      scanf("%d", &j);
      while(j--)
      {
        scanf("%d", &x);
        team[x] = i;
      }
    }
    while(scanf("%s", s))
    {
      if(s[0] == 'S') break;
      if(s[0] == 'D')
      {
        printf("%d\n", q[qt.front()].front());
        q[qt.front()].pop();
        if( q[qt.front()].empty() ) qt.pop();
      }
      if(s[0] == 'E')
      {
        int x;
        scanf("%d", &x);
        if( q[team[x]].empty() ) qt.push(team[x]);
        q[team[x]].push(x);
      }
    }
    printf("\n");
  } 
  return 0;
} 

下面这个是之前的错误代码。

#include <cstdio>
#include <iostream>
#include <map>
#include <vector>
#include <queue>
using namespace std;

map<int, int> team;//某个人对应这个人所在队伍的编号
//vector< queue<int> > q;//保存每个队伍的小队列 
queue<int> q[1010];
queue<int> qt;//在大队列中每个队伍的序号保存在此队列中
int main()
{
  freopen("New Text Document.txt","r",stdin);
  freopen("Output.txt","w",stdout);
  ios::sync_with_stdio(false);
  int t, kase = 0;
  string s;
  while(cin>>t && t)
  {
    if(kase) cout<<endl;
    cout<<"Scenario #"<<++kase<<endl;
    team.clear();
    //for(int i = 0; i < 1000; i++)
    //while(!q[i].empty()) q[i].pop();
    //q.clear();
    //while(!qt.empty()) qt.pop();
    for(int i = 0; i < t; i++)
    {
      int j, x;
      cin>>j;
      while(j--)
      {
        cin>>x;
        team[x] = i;
        //cout<<team[x]<<endl;
      }
    }
    while(cin>>s)
    {
      getchar();
      //cout<<s<<endl;
      if(s[0] == 'S') break;
      if(s[0] == 'D')
      {
        cout<<q[qt.front()].front()<<endl;
        q[qt.front()].pop();
        if( q[qt.front()].empty() ) qt.pop();
      }
      if(s[0] == 'E')
      {
        int x;
        cin>>x;
        if( q[team[x]].empty() ) qt.push(team[x]);
        q[team[x]].push(x);
      }
    }
  } 
  return 0;
} 

下面是刘汝佳标程

// UVa540 Team Queue
// Rujia Liu
#include<cstdio>
#include<queue>
#include<map>
using namespace std;

const int maxt = 1000 + 10;

int main() {
  int t, kase = 0;
  while(scanf("%d", &t) == 1 && t) {
    printf("Scenario #%d\n", ++kase);

    // 记录所有人的团队编号
    map<int, int> team; // team[x]表示编号为x的人所在的团队编号
    for(int i = 0; i < t; i++) {
      int n, x;
      scanf("%d", &n);
      while(n--) { scanf("%d", &x); team[x] = i; }
    }

    // 模拟
    queue<int> q, q2[maxt]; // q是团队的队列,而q2[i]是团队i成员的队列
    for(;;) {
      int x;
      char cmd[10];
      scanf("%s", cmd);
      if(cmd[0] == 'S') break;
      else if(cmd[0] == 'D') {
        int t = q.front();
        printf("%d\n", q2[t].front()); q2[t].pop();
        if(q2[t].empty()) q.pop(); // 团体t全体出队列
      }
      else if(cmd[0] == 'E') {
        scanf("%d", &x);
        int t = team[x];
        if(q2[t].empty()) q.push(t); // 团队t进入队列
        q2[t].push(x);
      }
    }
    printf("\n");
  }

  return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值