比赛对阵表(女排世界杯对阵表)

该博客详细介绍了如何编程实现女排世界杯比赛的对阵表,包括无轮空和存在轮空情况的队伍对阵。首先分析了不同队伍数量下的对阵规律,如4个队伍时的对阵表,并使用分治法实现8个队伍的对阵表。接着,通过比较和置零的方法处理存在轮空队伍的情况,例如3个和5个队伍。最后,提供了C++代码实现生成对阵表的功能。
摘要由CSDN通过智能技术生成

一、问题描述

2019女排世界杯,比赛赛制采用12支队伍单循环,两两捉对厮杀一场定胜负,依次进行。
比赛开始把12个队分成AB两个组进行,当同组每一个选手都碰面以后,再重新分组进行比赛,确保12支队伍每两支都相遇一次,最终将根据先胜负场次后积分的排名顺序。

编程实现:输入球队的数量,得出比赛的对阵表。

二、问题分析

提醒:
1.参赛队伍的数量不同可能会产生轮空的现象(某个队伍当天没有比赛)
2.需要分成两种情况来考虑,存在轮空和不会存在轮空
不会存在轮空:2、4、8、16、32…
存在轮空:3、5、6、7、9…

讨论参赛队伍的对阵情况:

(1)2个队伍的时候,比赛对阵表如图所示:

2个队伍的对阵表

a[0][0]=1;a[0][1]=2;
a[1][0]=2;a[1][1]=1;

(2)3个队伍的时候,会存在队伍轮空(当天不存在比赛)的情况。暂时不考虑。

(3)4个队伍的时候,对阵表如图所示

4个队伍的对阵表

可知以4个队伍的比赛赛程安排是建立在黄色区域(两只队伍的对阵表)为已知基础上的,且满足已下关系:

蓝色区域:对应的位置是黄色区域的对应位置上的值+2
绿色区域:对应的位置是黄色区域的对应位置上的值+2
红色区域:对应的位置是黄色区域的对应位置上的值相等

//绿色
for(i=0;i<=1;i++)
for(j=0;j<=1;j++)
	a[i][j+2]=a[i][j]+2;
//紫色
for(i=0;i<=1;i++)
for(j=0;j<=1;j++)
	a[i+2][j]=a[i][j]+2;

//蓝色
for(i=0;i<=1;i++)
for(j=0;j<=1;j++)
	a[i+2][j+2]=a[i][j];	

(4) 5,6,7只队伍暂时不考虑(均存在轮空的情况)。先直接考虑8个队伍的对阵表

8个队伍的对阵表

分治法实现:
把8个队伍的数据表示分成4小个区域。每个小区域又是由四个小区域构成。

区域之间的关系满足下列条件:

变化的值:
每一个小区域和左上角固定区域之间值的关系(蓝色区域:对应的位置是黄色区域的对应位置上的值+2)

三组for整体执行的次数:
(三次for构成一个完整的小区域,比如四只参赛队伍需要执行一次三组for。 整体执行次数则表示构成当前阵列需要执行多少次组合)

区域之间满足的关系

再考虑存在参赛队伍存在轮空的情况
(1)3个队伍的时候。

3个队伍的对阵表

3支队伍的对阵表等同于先计算4只队伍的参赛情况,然后去掉第4只队伍的对阵情况,再将前3只队伍的对阵列表中的含有第4只队伍的情况置零(即轮空),则实现了3只队伍的对阵表

(2)5个队伍的时候。

5支队伍的对阵表等同于先计算8只队伍的参赛情况,然后去掉第5只队伍之后的队伍的对阵情况,再将前5只队伍的对阵列表中的含有第5只队伍的之后的队伍的情况置零(即轮空),则实现了5只队伍的对阵表

综上所述:

(1)我们可以先直接计算不存在轮空现象的参赛队伍的情况

(2)然后再通过置零的方法,实现存在轮空对阵的参赛队伍的情况

(3)从而实现输入队伍数量,输出对阵表

三、代码实现

1.实现效果

实现效果如下:

程序实现效果

2.代码部分

#include<iostream>
#include<cmath>
#include <iomanip>
using namespace std;

int a[50][50];//对阵表最大容量
int b[6] = { 1,2,4,8,16,32};//不存在轮空现象的参赛队伍情况

//判断实际需要计算的对阵表(存在轮空现象会产生影响)
//比如 参赛队伍有5只 则只需要判断8只队伍的对阵表 然后将5只之后的情况 全部置零即可
//置零则表示当天对阵轮空
int compare(int N)
{
	for (int i = 0; i < 7; i++)
	{
		if (b[i] >= N)
		{
			return b[i];
			break;
		}
	}
}

void grouping(int N, int time)
{
	int i, j, k;

	//2个队伍的比赛对阵表作为已知值 
	a[0][0] = 1; a[0][1] = 2;
	a[1][0] = 2; a[1][1] = 1;
	for (k = 1; k <= (log(time) / log(2)) - 1; k++)
	{
		//每次变化的值t等于2的循环执行次数 t = pow(2,k)
		int t = pow(2, k);
		//绿色部分 
		for (i = 0; i <= t - 1; i++)
			for (j = 0; j <= t - 1; j++)
				a[i][j + t] = a[i][j] + t;
		//蓝色部分 
		for (i = 0; i <= t - 1; i++)
			for (j = 0; j <= t - 1; j++)
				a[i + t][j] = a[i][j] + t;
		//红色部分 
		for (i = 0; i <= t - 1; i++)
			for (j = 0; j <= t - 1; j++)
				a[i + t][j + t] = a[i][j];
	}

}
int main()
{
	int i, j, N;
	cout << "请输入队伍数量:";
	cin >> N;

	int time = compare(N);//time 统计队伍数量 比如6只队伍 需要先统计8只队伍的情况 然后将6之后的队伍情况置零即可
	grouping(N, time);

	//N 多少只参赛队伍
	//time 一共需要比赛的天数
	//零则表示当天对阵轮空
	for (j = 0; j < time; j++)
		cout << "\t第" << j + 1 << "天";
	cout << endl;

	for (i = 0; i < N; i++)
	{
		cout << "队伍" << i + 1;
		for (j = 0; j < time; j++)
		{
			if (a[i][j] > N)
			{
				a[i][j] = 0;
			}
			printf("\t%3d", a[i][j]);
		}
		printf("\n");
	}
	return 0;
}

代码小白,仅作学习记录📝

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值