比赛调度table C算法

Tournament scheduling table C algorithm

我需要制作一个 C 程序,creates/generates 时间表 table 比赛 "each against each other"。
共有16支球队(1至16号)和15轮比赛。 table 应该包含第 i 队和第 j 队再次比赛的回合,并且必须是二维数组,以行和列显示(见下文)。
此外,如果 i == j 则 a[i][j] = 0,因为在任何一轮中都没有球队与自己比赛。

任务条件我不是很清楚
我已经按照我的理解方式在上面进行了解释。
然而,经过几个小时的谷歌搜索,似乎基本上是循环赛。

我想应该是这样的:

teams   1   2   3   4   5   6   7   8   9   10  11  12  13  14  15  16
    1   0   1   2   3   4   5   6   7   8   9   10  11  12  13  14  15
    2   1   0   3   4   5   6   7   8   9   10  11  12  13  14  15  2
    3   2   3   0   5   6   7   8   9   10  11  12  13  14  15  1   4
    4   3   4   5   0   7   8   9   10  11  12  13  14  15  1   2   6
    5   4   5   6   7   0   9   10  11  12  13  14  15  1   2   3   8
    6   5   6   7   8   9   0   11  12  13  14  15  1   2   3   4   10
    7   6   7   8   9   10  11  0   13  14  15  1   2   3   4   5   12
    8   7   8   9   10  11  12  13  0   15  1   2   3   4   5   6   14
    9   8   9   10  11  12  13  14  15  0   2   3   4   5   6   7   1
    10  9   10  11  12  13  14  15  1   2   0   4   5   6   7   8   3
    11  10  11  12  13  14  15  1   2   3   4   0   6   7   8   9   5
    12  11  12  13  14  15  1   2   3   4   5   6   0   8   9   10  7
    13  12  13  14  15  1   2   3   4   5   6   7   8   0   10  11  9
    14  13  14  15  1   2   3   4   5   6   7   8   9   10  0   12  11
    15  14  15  1   2   3   4   5   6   7   8   9   10  11  12  0   13
    16  15  2   4   6   8   10  12  14  1   3   5   7   9   11  13  0

我不知道从哪里开始,实际上我唯一能做的就是用零填充主对角线。

这是我的代码,但它的输出不太好 table:

#include<stdio.h>

void print(int a[16][16]);
void schedule(int a[16][16]);

void main(){
    int a[16][16], i, j;
    schedule(a);
    print(a);
}

void schedule(int a[16][16]){
    for (int i = 0; i < 16; i++){
        for (int j = 0; j < 16; j++)
        if (i == j)
            a[i][j] = 0;
    }
}

void print(int a[16][16]){
   int k = 0;
   printf("teams: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16\n");
   for (int i = 0; i < 16; i++){
       k++;
       if (i < 10)
            printf("   %d   ", k);
       if (i >= 10)
            printf("   %d   ", k);

       for (int j = 0; j < 16; j++){
          if (a[i][j] == 0 && j < 10){
            printf("%d ", a[i][j]);
          }
          else if (a[i][j] == 0 && j >= 10) {
            printf(" %d ", a[i][j]);
          }
          if (j < 10)
            printf("  ");
          else
            printf("   ");
       }
       printf("\n");
   }

}

通过查看 table(按行或列),我注意到通常在 a[i][0] 中的数字之前的数字位于行的末尾 + 数字 "covered" 与 0。换句话说,在我看来,第一行向左移动,但这并不能帮助我想出一个算法。

使用这个来填充数组:

const int NofTeams=16;
int a[NofTeams][NofTeams];
int i,j;
for(i = 0; i< NofTeams-1; i++)
{
    for(j =0; j < NofTeams-1; j++)
    {
        if(i==j)
        {
            /* edge cases */
            a[i][NofTeams-1]=((i+j)+(i+j)/NofTeams)%NofTeams;
            a[NofTeams-1][j]=((i+j)+(i+j)/NofTeams)%NofTeams;
            a[i][j]=0;
        } else
        {
            a[i][j]=((i+j)+(i+j)/NofTeams)%NofTeams;
        }
    }
}
/* corner cases; [0][0] is diagonal */
a[0][NofTeams-1]=NofTeams-1;
a[NofTeams-1][NofTeams-1]=0;
a[NofTeams-1][0]=NofTeams-1;

诀窍是序列 ((i+j)+(i+j)/NofTeams)%NofTeams

这是为了永远不要打印太高的整数(最大值是团队数减 1):
%NofTeams.

这是为了增加团队数量(在 % 之后变成不需要的 0):
+(i+j)/NofTeams.

这个,结合其他的,是为了基本的循环赛:
(i+j)(两者中的第一个)。

否则诀窍是只用循环填充非边缘情况并专门处理边缘情况,即基本的 table-making 概念。

输出(简单的 2D table 打印,第一行和第一列根据您想要的输出):

    1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16
 1  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
 2  1  0  3  4  5  6  7  8  9 10 11 12 13 14 15  2
 3  2  3  0  5  6  7  8  9 10 11 12 13 14 15  1  4
 4  3  4  5  0  7  8  9 10 11 12 13 14 15  1  2  6
 5  4  5  6  7  0  9 10 11 12 13 14 15  1  2  3  8
 6  5  6  7  8  9  0 11 12 13 14 15  1  2  3  4 10
 7  6  7  8  9 10 11  0 13 14 15  1  2  3  4  5 12
 8  7  8  9 10 11 12 13  0 15  1  2  3  4  5  6 14
 9  8  9 10 11 12 13 14 15  0  2  3  4  5  6  7  1
10  9 10 11 12 13 14 15  1  2  0  4  5  6  7  8  3
11 10 11 12 13 14 15  1  2  3  4  0  6  7  8  9  5
12 11 12 13 14 15  1  2  3  4  5  6  0  8  9 10  7
13 12 13 14 15  1  2  3  4  5  6  7  8  0 10 11  9
14 13 14 15  1  2  3  4  5  6  7  8  9 10  0 12 11
15 14 15  1  2  3  4  5  6  7  8  9 10 11 12  0 13
16 15  2  4  6  8 10 12 14  1  3  5  7  9 11 13  0