比赛调度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
我需要制作一个 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