循环赛的日程安排

问题描述:

设有 n = 2 ^ k 个运动员要进行网球循环赛。现要设计一个满足以下要求的比赛日程表:

(1)每个选手必须与其他 n - 1 个选手各赛一次;
(2)每个选手一天只能参赛一次;
(3)循环赛在 n - 1 天内结束

按此要求将比赛日程表设计成有 n 行和 n - 1 列的一个表。在表中的第 i 行,第 j 列处填入第 i 个选手在第 j 天所遇到的选手。

在这里插入图片描述

思路:

采用分治策略,可将所有参加比赛的选手分成两部分,n = 2 ^ k 个选手的比赛日程表就可以通过 n = 2 ^(k-1)个选手的的比赛日程表来决定。递归的执行这样的分割,直到只剩下两个选手,比赛日程表的就可以通过这样的分治策略逐步构建。

从 0 开始对列编号, 0 列是自己跟自己打, 1 列是第一天比赛的对手号码。表的颜色相同部分是一样的。

队伍只有两个时:

                                                                 

队伍四个时: 

                                           

队伍八个时:

在这里插入图片描述故算法如下: 

初始化一个数组 a[n - 1][n - 1],输入:队伍数目 n 。

当n = 0的时候,a[0][0]=1;

当n > 0的时候,

1、把问题一分为二,递归地把左上角的矩阵生成好。
2、然后根据左上角矩阵,让右上角矩阵对应元素 + n / 2。
3、再把左下角元素和右上角元素对应起来,右下角元素和左上角元素对应起来。

Code:

#include<bits/stdc++.h>
using namespace std;
const int N = 1e3 + 10;
int a[N][N];

void Merge(int n){
	int m = n / 2;
	for(int i = 0;i < m;i ++ ){
		for(int j = 0;j < m;j ++){
		   a[i][j + m] = a[i][j] + m;//右上角 = 左上角 + m
		   a[i + m][j] = a[i][j + m];//左下角 = 右上角
		   a[i + m][j + m] = a[i][j]; //右下角 = 左上角
	    }
    }
}

void Solve(int n){
	if(n == 1) {
		a[0][0] = 1;
		return;
	}
	Solve(n / 2);
	Merge(n);
}

int main(){
	int n;
	cin >> n;
	Solve(n);
	for(int i = 0;i < n;i ++ ){
		for(int j = 0;j < n;j ++ ){
			cout << a[i][j] << " ";
		}
		puts("");
	}
	return 0;
} 

代码运行截图:

 

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

那就随便一点

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值