问题描述:设有n = 2的k次方个运动员要进行网球循环赛,现要设计一个满足以下要求的比赛日程表:
1.每个选手必须与其他n-1个选手各赛一次;
2.每个选手一天只能参赛一次;
3.循环赛在n-1天内结束;
要求设计成n-1行和n列的表,第i行,j列代表第i个选手在第j天遇到的对手, 其中1<=i<=n,1<=j<=n-1;
思路:可以按照分治策略把n个选手的比赛日程表分解成n/2个选手的比赛日程表,直到只剩下两个选手时,比赛日程表就很简单了, 1 2
2 1
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define MAX 100 //(tox,toy)代表源方阵左上角顶点坐标
int n,a[MAX][MAX]; //(x,y)代表要进行复制的方阵的顶点坐标
void Copy(int tox,int toy,int x,int y,int r)
{
int i,j;
for(i = 0; i<r; i++)
for(j = 0; j<r; j++)
{
a[tox+i][toy+j] = a[x+i][y+j];
}
}
void table()
{
int i,r;
for(i = 0; i<n; i++)//构造课程表第一行
a[0][i] = i+1; //n = 8时
for(r = 1; r<n; r <<= 1)//1,2,4,先1*1的复制,再2*2的复制,再4*4的复制
for(i = 0; i<n; i+=2*r)//0,2,4,6/0,4/0
{
Copy(r,r+i,0,i, r);
Copy(r,i, 0,r+i,r);
}
}
int main()
{
while(~scanf("%d",&n))
{
memset(a,0,sizeof(a));
table();
int i,j;
for(i= 1;i<n;i++)
{
for(j = 0;j<n;j++)
printf("%d ",a[i][j]);
printf("\n");
}
}
}