问题描述:
设有n=2^k个运动员要进行网球循环赛。现要设计一个满足以下要求的比赛日程表:
(1)每个选手必须与其他n-1个选手各赛一次;
(2)每个选手一天只能参赛一次;
(3)循环赛在n-1天内结束;
(4)每个元素占用空间为四个字符;请按此要求将比赛日程表设计成有n行和n-1列的一个表。在表中的第i行,第j列处填入第i个选手在第j天所遇到的选手。其中1≤i≤n,1≤j≤n-1。8个选手的比赛日程表如下表:
选手|对手|时间 第一天 第二天 第三天 1 2 3 4 2 1 4 3 3 4 1 2 4 3 2 1
思路:
通过这个表格很难给出结果,因此分治法;可以先选两个选手:
1 | 2
2 | 1
同理,四个选手:
1 2 | 3 4
2 1 | 4 3
3 4 | 1 2
4 3 | 2 1
可看出:矩阵右上角与左下角对称,以最初的1×1方阵按上述规则生成2×2方阵,然后生成4×4方阵,直到完成整个循环比赛表为止,用变量h表示当前方阵的大小,也就是要生成下一个方阵的一半;
总是对以某三点组成的正方形角逐步更新;
#include<cstdio>
#include<iostream>
#include<iomanip>
#include<cstdlib>
using namespace std;
int pow(int x,int n) {
int res = 1;
for(int i = 0; i < n; i++) res *= x;
return res;
}
int main() {
int m, n, h = 1;
int a[35][35];
a[1][1] = 1;
cin >> m;
n = pow(2, m);
do {
//cout << "******" <<endl;
for(int i = 1; i <= h; i++) {
//cout << "***for1*** " << i <<endl;
for(int j = 1; j <= h; j++) {
//cout << "***for2*** " << j <<endl;
a[i][j + h] = a[i][j] + h; //构造右上角方阵
a[i + h][j] = a[i][j + h]; //构造左下角方阵
a[i + h][j + h] = a[i][j]; //构造右下角方阵
}
}
h *= 2;
}while(!(h == n));
for(int i = 1; i <= n; i++) {
for(int j = 1; j <=n; j++)
cout << setw(4) << a[i][j];
cout << endl;
}
return 0;
}
setw()函数是控制元素所占空间大小,头文件为iomanip