ACM学习历程—HDU 1276 士兵队列训练问题(队列)

Description

某部队进行新兵队列训练,将新兵从一开始按顺序依次编号,并排成一行横队,训练的规则如下:从头开始一至二报数,凡报到二的出列,剩下的向小序号方向靠 拢,再从头开始进行一至三报数,凡报到三的出列,剩下的向小序号方向靠拢,继续从头开始进行一至二报数。。。,以后从头开始轮流进行一至二报数、一至三报 数直到剩下的人数不超过三人为止。
 

Input

本题有多个测试数据组,第一行为组数N,接着为N行新兵人数,新兵人数不超过5000。
 

Output

共有N行,分别对应输入的新兵人数,每行输出剩下的新兵最初的编号,编号之间有一个空格。
 

Sample Input

2
20
40
 

Sample Output

1 7 19
1 19 37

题目大意就是一个队列报数,第一次12报数,报到2的出列;第二次123报数,报到3的出列;如此循环往复,直到队列人数不超过3.

这里采用两个队列交替使用,对于12报数的情况,只有报到1的才会入另一个队。

对于123的,自然是报到12的入另一个队。

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <set>
#include <stack>
#include <map>
#include <queue>
#include <string>
#include <algorithm>
#define LL long long

using namespace std;

int n;

void work()
{
    queue<int> q[2];
    bool now = 0;
    int num;

    for (int i = 1; i <= n; ++i)
        q[now].push(i);

    for (;;)
    {
        if (q[now].size() <= 3)
            break;
        num = 0;
        now = !now;
        while (!q[!now].empty())
        {
            num = num%2+1;
            if (num != 2)
                q[now].push(q[!now].front());
            q[!now].pop();
        }

        if (q[now].size() <= 3)
            break;
        num = 0;
        now = !now;
        while (!q[!now].empty())
        {
            num = num%3+1;
            if (num != 3)
                q[now].push(q[!now].front());
            q[!now].pop();
        }
    }
    bool flag = false;
    while (!q[now].empty())
    {
        if (flag)
            printf(" ");
        printf("%d", q[now].front());
        q[now].pop();
        flag = true;
    }
    printf("
");
}

int main()
{
    //freopen("test.in", "r", stdin);
    int T;
    scanf("%d", &T);
    for (int times = 0; times < T; ++times)
    {
        scanf("%d", &n);
        work();
    }
    return 0;
}
原文地址:https://www.cnblogs.com/andyqsmart/p/4665468.html