我需要制作一个 C 程序,为“相互对抗”的锦标赛创建/生成时间表。
共有16支球队(1至16号)和15轮比赛。该表格应包含第 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
我不知道从哪里开始,实际上我唯一能做的就是用零填充主对角线。
这是我的代码,但它不能很好地输出表格:
#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");
}
}
通过查看表格(按行或列),我注意到通常位于 a[i][0]
中的数字之前的数字位于行的末尾 +用 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)
(两者中的第一个)。
否则诀窍是只用循环填充非边缘情况并专门处理边缘情况,即基本的制表概念。
输出(简单的 2D 表格打印,第一行和第一列根据您想要的输出):
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
关于c - 比赛排类表C算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50186119/