用递归方法解决循环日程表问题
题目:有n=2的K次方个运动员进行网球循环赛,需要设计比赛日程表。每个选手必须与其他n-1个选手个赛一次,每个选手一天只能赛一次,循环赛一共进行n-1天。按此要求设计一张比赛日程表,它有n行n-1列,第i行第j列为第i个选手第j天遇到的选手。
分析:本题的方法有很多,递归是其中一种比较容易理解的方法。如下图所示,k=3时的一个可行解,它是4块拼起来的。左上角是k=2时的一组解,左下角是左上角每个数加4得到的,而右上角,右下角分别是左下角,左上角复制得到的。
同理,k=2的一组解,可以看做k=1时解的变换得到的,k=1时,可以看做k=0时变换得到的。k=0时,只有一个元素,赋值1.
源代码:
#include<stdio.h>
#include<string.h>
#define N 100
void circle_table(int A[N][N],int k)
{
int add=0,i,j;
if(k==0){A[k][k]=1;}
else{
circle_table(A,k-1);
add=(1<<k-1);
//printf("\nadd=%d\n",add);
for(i=add;i<add*2;i++)
for(j=0;j<add;j++){
A[i][j]=A[i-add][j]+add;
A[i-add][j+add]=A[i][j];
}
for(i=add;i<add*2;i++)
for(j=add;j<add*2;j++){
A[i][j]=A[i-add][j-add];
}
}
}
int main(){
int k,i,j;
int A[N][N];
scanf("%d",&k);
memset(A,0,sizeof(A));
printf("%d,%d\n",A[0][0],1<<k);
circle_table(A,k);
for(i=0;i<(1<<k);i++){
for(j=0;j<(1<<k);j++)
{printf("%d ",A[i][j]);}
printf("\n");
}
return 0;
}
需要注意的地方,当函数参数为二位数组时,需要至少指定列元素的个数,不然会报错missing subscript
运行截图: