循环赛日问题:
设有n=2^k个选手参加循环赛,要求设计一个满足以下要求比赛日程表:
1)每个选手必须与其它n-1个选手各赛一次;
2)每个选手一天只能赛一次。
分析,按照上面的要求,可以将比赛表设计成一个n行n-1列的二维表,其中第i行第j列的元素表示和第i个选手在第j天比赛的选手号。
思路:
一开始我以为枚举全排列然后满足每行每列不出现同样的数字就行了,然后发现还要满足一个人一天只能赛一次,然后就不行了,(构造了一个矩阵满足每行每列不出现相同数字,可惜 了)。
solved是我构造的矩阵。(可以省略)
然后这个题用分治的方法去做就行了,思路不是很难,就是左上角复制到右下角,右上角复制到左下角这个思路可能不太容易想到,如果知道了这个关系,就可以分四等分构造了。还有就是循环变量的规律也不太好找(花了我不少时间)。
这个递归应该也能做。。。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e3 + 10;
int c[maxn][maxn];
void solved(){
int n;cin>>n;
for(int i=1;i<=n;i++){
int cnt = 1;
for(int j=1;j<=i;j++){
if(j == 1)c[i][j] = i;
else c[i-cnt++][j] = i;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i + j == n + 1)continue;
c[n-j+1][n-i+1] = n-c[i][j];
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cout<<c[i][j]<<" ";
}
cout<<endl;
}
}
void trans(int x2,int y2,int x1,int y1,int len){
int t;
for(int i=x1;i<x1+len;i++){
t = y2;
for(int j=y1;j<y1+len;j++){
c[x2][t++] = c[i][j];
}
x2++;
}
}
int main(){
//solved();
int k;cin>>k;
int n = 1<<k;
for(int i=0;i<n;i++){
c[1][i] = i+1;
}
for(int i = 1;i < n;i <<= 1){
for(int j = 0;j < n; j +=i*2){
trans(i+1,j,1,i,i);//左下
trans(i+1,j+i,1,j,i);//右下
}
}
for(int i=1;i<=n;i++){
for(int j=0;j<n;j++){
cout<<c[i][j]<<" ";
}
cout<<endl;
}
}
附上一张图片方便理解: