循环赛日程安排问题(分治法)

循环赛日程安排问题(分治法),第1张

循环赛日程安排问题(分治法)

问题描写叙述:

设有n(n=2^k)支队伍參加循环赛,循环赛共进行n-1天,每支队伍要与其它n-1支队伍比赛一场,
且每支队伍每天必须比赛一场,不能轮空。试按此要求为比赛安排日程。

算法思路:

   我们先安排奇数下标位置与偶数下标位置之间的比赛,就有n/2场,方法非常easy,
   team[2k]=2k,全部奇数号组成一个序列[1,3...n-1],
   然后循环移动n/2-1次(比方第2个序列就是[3,5...n-1,1]),
   然后将该序列填充在team的奇数位置上。
   接下来将队伍一分为二,奇数为一组,偶数为一组,
   分配安排其内部比赛(由于奇偶数之间前面已经安排过了啦)。
   以奇数组[1,3,5,7]为例(以n=8为例说明),
   我们仍然先安排奇数下标位置与偶数下标位置之间的比赛,
   也就是[15]与[37]之间的比赛,共同拥有2场(n/4)。
   接下来,再将队伍一分为二,得到[15],[37],[04],[26],
   对每一部分,仍然是先安排奇数下标位置与偶数下标位置之间的比赛,共1场(n/8)。
   此时已不可再分出子队伍,计算结束。

对照赛安排编号:

从前文的分析能够看出,我们产生比赛日程安排是有规律可循,
先产生n/2,然后是n/4,...直到最后1场。因为n=2^k,
那么这些安排场次总数为2^(k-1)+2^(k-2)...+1=2^k-1=n-1,
恰好相符(其实是必定的)。
这样,对于给定一个编号id,我们首先能够判定相应场次安排须要进行几次队伍分裂。
方法非常easy,比如n=8,id=6,因为一次分烈得到n/2=4场,再次分裂可得n/4=2场,于是两次分裂就可以。
同一时候id-4=2,也就是说两次分裂后的第2个赛场安排,这个2用于对子队伍移位计算使用。

图示

代码

#include
#include
#include
#include
#include
using namespace std;

string transform(int num)
{
	bool add = false;
	if (num < 10) {
		add = true;
	}
	stack temp_stack;
	int temp_num;
	while (num != 0)
	{
		temp_num = num % 10;
		num /= 10;
		char temp_char = '0' + temp_num;
		temp_stack.push(temp_char);
	}
	string str;
	if (add) {
		str += '0';
	}
	while (!temp_stack.empty())
	{
		str += temp_stack.top();
		temp_stack.pop();
	}
	return str;
}

void game(vector arr, int day, vector> &result)
{
	int len = arr.size() / 2;
	for (int i = 0; i < len; i++)
	{
		for (int k = 0; k < 2 * len; k += 2)
		{
			string str;
			str += transform(arr[k]);
			str += "--";
			str += transform(arr[k + 1]);
  			result[day + i].emplace_back(str);
		}
		if (i == len - 1){
			break;
		}
		int rear = arr[0];
		for (int j = 0; j < arr.size() - 2; j += 2)
		{
			arr[j] = arr[j + 2];
		}
		arr[arr.size() - 2] = rear;
	}
	
	if (len == 1){
		return;
	}

	vector left(len), right(len);
	for (int i = 0; i < len; i++)
	{
		left[i] = arr[2 * i];
		right[i] = arr[2 * i + 1];
	}
	day += len;
	game(left, day, result);
	game(right, day, result);
}

void print(vector> &result)
{
	cout<<"循环赛日程安排为:"<>k;
	int sum = (int) pow((double) 2, (double) k);
	vector arr(sum);
	for (int i = 0; i < sum; i++)
	{
		arr[i] = i + 1;
	}
	vector> result(sum - 1);
	game(arr, 0, result);
	print(result);
	return 0;
}

//输入案例
//4

博文参考链接

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5690889.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存