题意:
有2k个运动员进行网球循环赛,设计赛事表使得:
- 每个选手与其他n-1个选手各赛一次
- 每个选手每天只能赛一次
- 循环赛在n-1天内结束
日程表第i行第j列表示第i个选手在第j天遇到的选手
分析:
考虑k=3,n=8的情况,利用分治思想,将所有选手不停的分为两组,最终转化为只剩两个人进行比赛,再根据两个人的比赛安排得到整体赛事表。
- 先列出要比赛的8位选手
for(int i = 1; i <= 8; i++) a[1][i] = i;
- 考虑表格前两行,两个人一组,将表格分成n/2块,将每一块的左上角元素抄到右下角,右上角元素抄到左下角
- 继续考虑前四行,四个人一组,将表格分成n/4块,同理将每一块的左上角元素抄到右下角,右上角元素抄到左下角
- 最后考虑前八行,八个人一组,将表格看成一个整体,同理将左上角的元素抄到右下角,右上角元素抄到左下角
- 最终获得日程表
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|
2 | 1 | 4 | 3 | 6 | 5 | 8 | 7 |
3 | 4 | 1 | 2 | 7 | 8 | 5 | 6 |
4 | 3 | 2 | 1 | 8 | 7 | 6 | 5 |
5 | 6 | 7 | 8 | 1 | 2 | 3 | 4 |
6 | 5 | 8 | 7 | 2 | 1 | 4 | 3 |
7 | 8 | 5 | 6 | 3 | 4 | 1 | 2 |
8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
代码:
#include<cstdio>
#include<cmath>
#include<iostream>
using namespace std;
const int maxn = 10005;
int a[maxn][maxn];
int main (void)
{
int k, m = 1;
cin>>k;
int t = pow(2,k);
int n = t;
//第一行
for(int i = 1; i <= n; i++) a[1][i] = i;
//依次分块,并将每块的左上角元素抄到右下角,右上角抄到左下角
for(int i = 1; i <= k; i++){
n /= 2;
for(int p = 1; p <= n; p++){
for(int j = 1; j <= m; j++){
for(int k = 1; k <= m; k++){
a[j+m][k+2*m*(p-1)] = a[j][m+k+2*m*(p-1)];
a[j+m][m+k+2*m*(p-1)] = a[j][k+2*m*(p-1)];
}
}
}
m *= 2;
}
//打印表格
for(int i = 1; i <= t; i++){
for(int j = 1; j <= t; j++){
cout<<a[i][j]<<' ';
}
cout<<endl;
}
}