【C语言】【分治算法】循环赛日程安排问题

题目要求

设有 n = 2 k n=2^{k} n=2k个选手要进行网球循环赛,要求设计一个满足以下要求的比赛日程表:

(1)每个选手必须与其他n-1个选手各赛一次;

(2)每个选手一天只能赛一次。

按此要求,可将比赛日程表设计成一个 n 行n-1列的二维表,其中,第 i 行第 j 列表示和第 i 个选手在第 j 天比赛的选手。

解题思路

这个没什么好办法,我是话了n=2,n=4,n=8的情况找规律做的
假设不按题目要求来,比了n天比赛,第一天都是选手自己和自己比,方便找规律
如果只有一个选手,那就是自己和自己比
如果有两个选手,是这样的

1 2
2 1

正对角线元素相同,逆对角线元素相同
有4个选手是这样的

1 2 3 4
2 1 4 3
3 4 1 2
4 3 2 1

可以看到,左上角分块矩阵和右下角是一致的,那就可以用分治的思想来处理了,先处理左上角,再处理右上角,左下角复制右上角,右下角复制左上角。

C语言实现

#include 
#include
#include
//分治递归,mStart是分治区域的起始的纵坐标,mEnd是分治区域结束的纵坐标
//nStart是分治区域的起始的横坐标,nEnd是分治区域的结束的横坐标
void arrange(int** a, int mStart, int mEnd, int nStart, int nEnd)
{
	//只有一个参赛选手,只能自己与自己比
	if (mStart == mEnd && nStart == nEnd)
	{
		a[mStart][nStart] = nStart;
		return;
	}
	//有两个选手,矩阵对角线相等
	if (mStart + 1 == mEnd && nStart + 1 == nEnd)
	{
		//主对角线相等
		a[mStart][nStart] = nStart;
		a[mEnd][nEnd] = nStart;
		//逆对角线相等
		a[mStart][nEnd] = nEnd;
		a[mEnd][nStart] = nEnd;
		return;
	}
	int mMid = (mStart + mEnd) / 2;
	int nMid = (nStart + nEnd) / 2;
	arrange(a, mStart, mMid, nStart, nMid);//左上角分块矩阵
	arrange(a, mStart, mMid, nMid + 1, nEnd);//右上角分块矩阵
	//将左上角分块矩阵复制到右下角
	for (int i = mMid + 1; i <= mEnd; i++)
	{
		for (int j = nMid + 1; j <= nEnd; j++)
		{
			a[i][j] = a[i - mMid][j - nMid];
		}
	}
	//将右上角分块矩阵复制到左下角
	for (int i = mMid+1; i <= mEnd; i++)
	{
		for (int j = nStart; j <= nMid; j++)
		{
			a[i][j] = a[i - (mMid-mStart+1)][j + (nMid - nStart+1)];//mMid-mStart+1是左下角纵坐标到上半矩阵对应纵坐标的距离,nMid - nStart+1同理
		}
	}
}
//打印矩阵
void printMatrix(int** a, int m, int n)
{
	printf("参赛\n选手\t");
	for (int i = 2; i < n; i++)
	{
		printf("第%d天\t", i - 1);
	}
	printf("\n");
	for (int i = 1; i < m; i++)
	{
		for (int j = 1; j < n; j++)
		{
			printf("%d\t", a[i][j]);
		}
		printf("\n");
	}
}
int main()
{
	int m = 0;//参赛选手人数
	printf("请输入参赛选手的个数:\n");
	scanf("%d", &m);
	if ((m & (m-1)) != 0)//判断2的n次方的经典条件(m & (m-1))的结果为0就是,注意加括号,符号优先级要注意
	{
		printf("参赛选手必须为2的n次方!\n");
		return 0;
	}
	int** matrix = (int**)malloc((m+1) * sizeof(int*));
	for (int i = 0; i < (m+1); i++)
	{
		matrix[i] = (int*)malloc((m + 1) * sizeof(int));
		memset(matrix[i], 0, (m + 1) * sizeof(int));//将二维数组每一行置为0
	}
	arrange(matrix, 1, m, 1, m);
	printMatrix(matrix, m+1, m+1);
}

测试结果

你可能感兴趣的:(算法,c语言,算法)