循环赛——c++实现

大家好,我是慢慢努力的小刘。最近因为学业过重,一直没有给大家更新,今天中午刚好有时间给大家更新一篇文章。这次给大家更新的文章的内容是我们算法设计的一次实验题目,如果对大家有帮助得话,那就请大家动动小手点个赞,关个注!谢谢啦。

问题描述:

设有n=2k个运动员要进行网球循环赛。现要设计一个满足以下要求的比赛日程表:⑴每个选手必须与其他n-1个选手各赛一次;⑵每个选手一天只能赛一次;⑶循环赛一共进行n-1天。按此要求可将比赛日程表设计成有n行和n列的一个表。表中第一列是选手编号,表中第i行和第j列(j>1)处填入第i个选手在第j天所遇到的选手。例如8个选手的日程表安排如右图所示。

算法思想及处理过程:

分治策略:
1:将所有参赛的选手分为两部分
    n=2^k个选手的比赛日程表就可以通过为n/2=2^(k-1)个选手设计的比赛日程表来决定。
2:递归地执行这种分割
3:直到只剩下2个选手比赛日程表的制定就变得足够简单,只要让这2个选手进行比赛即可

思想及处理过程:
1:求解过程是自底向上的迭代过程,第一列是选手的编号其中左上角和左下角分别为选手1至选手4以及选手5至选手8前3天的比赛日程
2:将左上角部分的所有数字按其对应位置抄到右下角,将左下角的所有数字按其对应位置抄到右上角,这样,就分别安排好了选手1至选手4以及选手5至选手8在后4天的比赛日程,具有多个选手的情况可以依此类推。

图解:

当n=2时:                      当n=4时:

         

●把求解2k个选手比赛日程问题划分成依次求解21、22、…、2k个选手的比赛日程问题,换言之,2k个选手的比赛日程是在2k-1个选手的比赛日程的基础上通过迭代的方法求得的。
●在每次迭代中,将问题划分为4部分:
①左上角
●左上角为2k-1个选手在前半程的比賽日程;
②左下角
●左下角为另2k-1个选手在前半程的比赛日程,由左上角加2K-1得到,例如22个选手比賽,左下角由左上角直接加2得到,23个选手比赛,左下角由左上角直接加4得到;
右上角
●将左下角直接抄到右上角得到另2k-1个选手在后半程的比赛日程;
④右下角
●将左上角直接抄到右下角得到2k-1个选手在后半程的比赛日程;
●算法设计的关键在于寻找这4部分元素之间的对应关;

代码演示:

#include<iostream>
#include<math.h>
using namespace std;

void OutPut(int n, int **a)
{
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= n; j++)
		{
			cout << a[i][j] << " ";
		}
		cout << endl;
	}
}
void Combine(int t, int n, int** a)
{
	int i, j;
	for (i =t; i <=t+n/2-1 ; i++)
	{
		for (j = n / 2 + 1; j <= n; j++)
		{
			a[i][j] = a[i + n / 2][j - n / 2];
		}
	}
	for (i = t + n / 2; i <= t + n - 1; i++)
	{
		for (j = n / 2 + 1; j <= n; j++)
		{
			a[i][j] = a[i - n / 2][j - n / 2];
		}
	}
}
void GameTable(int t,int n, int** a)//分治递归
{
	int i, j;
	if (n == 2)
	{
		a[t][1] = t;
		a[t][2] = t+1;
		a[t+1][1] =t+1;
		a[t+1][2] = t;
	}
	else {
		GameTable(t, n / 2, a);//处理前半组比赛;
		GameTable(t + n / 2, n / 2, a);//处理后半组比赛;
	}
	Combine(t, n, a);//将若干个子问题合并成一个
}
int main()
{
	int k;//k是n=2^k个运动员要进行网球循环赛
	cout << "请输入正整数2的指数k的值:" << endl;
	cin >> k;
	while (k<=0)
	{
		cout << "你输入的k值有误,请重新输入k" << endl;
		cin >> k;
		if (k > 0)
		{
			break;
		}
	}
	int n = pow(2, k);
	int i;
	int t = 1;//表示第一个比赛选手;
	int** a = new int* [n];//动态分配为分配二维数组a;
	for (i = 1; i <= n; i++)
	{
		a[i] = new int[n];
	}
	GameTable(t,n,a);
	cout << "循环赛日程表:" << endl;
	OutPut(n, a);
	return 0;
}

总结:

每天给自己一些鼓励的话语:不积硅步,无以至千里。加油各位兄弟。

  • 18
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值