题目描述
设有n个选手的网球循环比赛,其中n=2^k(0≤k<7)。现要设计一个满足以下条件的比赛日程表:
(1)每名选手要与其他n−1名选手都进行一次比赛;
(2)每名选手每天只赛一次;
(3)整个比赛共进行n−1天,要求每天没有选手轮空。
输入描述
选手人数n(n≤100),n只能为2的整数次幂。
输出描述
N阶方阵A[1..n,0..n−1],当j>0时,A[i,j]表示第i名运动员在第j天所遇到的比赛对手(A[i,0]=i),每个数据占5位宽度。
输入
4
输出
1 2 3 4 2 1 4 3 3 4 1 2 4 3 2 1
历时三天,终于解决。放弃循环,苦想递归!(难道循环难吗,不难,只是阻挡我装伯夷的步伐
//分析:
/*
通过观察题目很容易看出,这是一道分治思想的题目
那就不得不用递归来想一下了
把整个图看成一个坐标系的四个象限
① | ②
—— + ——
③ | ④
所以我们要做的是借助拷贝函数进行数据的传递:
①->④ ②->③
但是我们只有第一行的数据,这就需要我们把整个问题细分成无数个小部分
这里就用到了我们的分割函数。
所以我们先割后拷
这样就可以得出答案了
*/
#include<bits/stdc++.h>
using namespace std;
int a[101][101];
int n;
void copy(int x,int y,int cx,int cy,int form) {//拷贝函数
//x y 初始位置
//cx cy 目标位置
//form 规模
for(int i=0; i<form; i++)
for(int j=0; j<form; j++)
a[cx+i][cy+j]=a[x+i][y+j];
}
void part(int form,int x,int y) {//分割函数
if(form==1)
return;
int t=form>>1;
part(t,x,y);//先割后拷
part(t,x,y+t);
copy(x,y,x+t,y+t,t);
copy(x,y+t,x+t,y,t);
}
int main() {
cin>>n;
for(int i=1; i<=n; i++)
a[1][i]=i;
part(n,1,1);
for(int i=1; i<=n; i++) {
for(int j=1; j<=n; j++)
printf("%5d",a[i][j]);
cout<<"\n";
}
return 0;
}
//CSDN:panjyash原创 拒绝转载