问题描述:
对于n=2^k个选手,设计一个满足以下要求的比赛日程表。
条件1:每个选手必须与其他n-1个选手各赛一次
条件2:每个选手一天只能赛一次
条件3:循环赛一共进行n-1天
问题的求解方法:
分治,将所有选手分成两半,n个选手的比赛日程表就可以通过n/2个选手设计的比赛日程表来决定
递归进行分割,直到只剩下两个选手。
倒退,首先确定日程表第一行,求得第二行,然后求得三四行。。。。。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int a[100][100];
void SetTable(int k,int n)
{
for(int j=1;j<=n;j++)//首先设置日程表第一行
a[1][j]=j;
int m=1;//记录了填充的起始行,同时也是填充块数的宽度,从最初行宽度1开始算起
for(int s=1;s<=k;s++)//共完成k次大循环
{
n=n/2;//记录填充块的个数
for(int t=1;t<=n;t++)
{
for(int i=m+1;i<=2*m;i++)
{
for(int j=m+1;j<=2*m;j++)
{
a[i][j+(t-1)*m*2]=a[i-m][j+(t-1)*m*2-m];//左上方赋值给右下方
a[i][j+(t-1)*m*2-m]=a[i-m][j+(t-1)*m*2];//右上方赋值给左下方
}
}
}
m=m*2;
}
}
int main()
{
memset(a,0,sizeof(a));
int n=1;
int k;
cin>>k;
for(int i=1;i<=k;i++)
{
n=2*n;
}
SetTable(k,n);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
cout<<a[i][j]<<" ";
}
cout<<endl;
}
return 0;
}