持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第23天,点击查看活动详情
1.问题描述
设有n=2k个选手要进行网球循环赛,设计一个满足以下要求的比赛日程表:(1)每个选手必须与其他n-1个选手各赛一次。(2)每个选手一天只能赛一次。(3)循环赛在n-1天之内结束。
1.1产生的疑问
有没有可能因为是随机配,打到后面,没跟A打过的人跟别人打了,然后A轮空了。这种事情有可能发生吗?
2.思路及想法
- 每一天每一个球员跟哪个球员打,这样一个二维数组可以记录的下。
- 但是需要额外多一个二维数组,两两之间打过的要做记录,而且表格要不断进行更新。
- 今天这位选手打了没可以直接借用第一点的那个二维数组,值不为0就是打过了。因为是两两配对,所以2^k次方个人每天都能确保有一场比赛。
3.什么是分治法
分治法指的是将原问题递归地分成若干个子问题,直到子问题满足边界条件,停止递归,将子问题逐个解决(一般是同种方法),将已经解决的子问题合并,最后,算法会层层合并得到原问题的答案。
3.1分治算法步骤
- 分:递归地将问题分解为各个的子问题(性质相同的,相互独立的子问题)。
- 治:将这些规模更小的子问题逐个击破。
- 合:将已解决的问题逐层合并,最终得出原问题的解。
3.2分治算法适用条件
- 问题的规模缩小到一定的规模就可以较容易地解决。
- 问题可以分解为若干个规模较小的模式相同的子问题,即该问题具有最优子结构性质。
- 合并问题分解出的子问题的解可以得到问题的解。
- 问题所分解出的各个子问题之间是独立的,即子问题之间不存在公共的子问题。
4代码实现
#include<iostream>
#include<math.h>
using namespace std;
int a[100][100];//定义一百行一百列
void xunhuan(int x,int y,int n)
{
int mid = n / 2;
if (n >= 4)
{
xunhuan(x, y, mid);//分解后第一部分左上角数字的位置
xunhuan(x, y + mid, mid); //分解后第二部分左上角数字的位置
}
for (int i = x+mid; i < x + n; i++)
{
for (int j = y; j < y + mid ; j++)
{
a[i ][j ] = a[i - mid][j+mid];
}
}
for (int i = x + mid; i < x + n; i++)
{
for (int j = y+mid; j <y + n; j++)
{
a[i][j] = a[i - mid][j - mid];
}
}
}
int main()
{
int k;
cin >> k;
int n;
n = pow(2, k);//人数
for (int j = 1; j <= n; j++)//将第一列先赋值
{
a[1][j] = j;
}
xunhuan(1, 1, n);
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
cout << a[i][j]<<" ";
}
cout << endl;
}
}