Dancepted

Dancing Acceped!

ZOJ5833 Tournament(递归打表)

题目链接:传送门

假思路:

  根据题意要求,只能按字典序最小的方法安排比赛。

  所以第一场必定是1和2比,3和4比。。。。

  选手:1 2

  对手:2 1

  根据要求如果1与2比过赛了,1再与其它的人(不妨设为a)比赛的话,2就必须与(第一场与a比赛的人,不妨设为b)比赛。

  因为要求字典序小,所以1应该和a、b中较小者先比赛,再与较大者比赛,那么不妨令a < b,则1、2、a、b比赛时就会是这样安排的:

  选手:1 2 a b

  对手:2 1 b a

        a b 1 2

        b a 2 1

  因为要求字典序最小,所以a、b应当先与3、4比赛:

  选手:1 2 3 4

 

  对手:2 1 4 3

 

        3 4 1 2

 

        4 3 2 1

  (然后陈某人脑子一片空白打了个表。。。。验证一下能不能比k轮就交上去了。)

  同样地,1已经与2、3、4比过赛了,那么它再碰见a、b、c、d(不妨令a < b < c < d)时,就会因为字典序要求依次与a、b、c、d比赛。(a、b、c、d取到最小,所以对应了5、6、7、8)

  选手:1 2 3 4 a b c d

  对手:2 1 4 3 b a d c

      3 4 1 2 c d a b

     4 3 2 1 d c b a

      a b c d 1 2 3 4

     b a d c 2 1 4 3

     c d a b 3 4 1 2

      d c b a 4 3 2 1

  这样安排首先能保证字典序最小和满足第四个规则,其次也能使得比赛的轮数尽量多(较大的数与前面的数比赛的时间更迟),所以答案就在表里。验证表中的前k行的前n个数是否出现了比n大的数即可判断是否为Impossible。

代码:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int MAX_N = 1e3 + 50;

int N, K;
int mat[MAX_N][MAX_N];

void work(int len)
{
    if (2*len > MAX_N)
        return;
    for (int i = 1; i <= len; i++) {
        for (int j = 1; j <= len; j++) {
            mat[i+len][j] = mat[i][j] + len;
            mat[i+len][j+len] = mat[i][j];
            mat[i][j+len] = mat[i][j] + len;
        }
    }
    work(2*len);
}

void init()
{
    mat[1][1] = 1; mat[1][2] = 2;
    mat[2][1] = 2; mat[2][2] = 1;
    work(2);
}

bool check()
{
    for (int i = 2; i <= K+1; i++) {
        for (int j = 1; j <= N; j++) {
            if (mat[i][j] > N) {
                return false;
            }
        }
    }
    return true;
}

int main()
{
    init();
    int T;
    cin >> T;
    while (T--) {
        scanf("%d%d", &N, &K);
        bool ok = check();
        if (!ok) {
            puts("Impossible");
            continue;
        }
        for (int i = 2; i <= K+1; i++) {
            bool firstprint = true;
            for (int j = 1; j <= N; j++) {
                if (firstprint)
                    firstprint = false;
                else
                    printf(" ");
                printf("%d", mat[i][j]);
            }
            puts("");
        }
    }
}
View Code

 

posted on 2018-11-11 22:42  Danceped  阅读(265)  评论(0编辑  收藏  举报

导航