分治法——循环赛日程表

分治法——循环赛日程表_第1张图片

总共2^k个选手,正好为2的整数幂,每位选手每天只能比一次,必须与其他选手各比赛一次,总共n-1天。如图所示以天数为横坐标,以运动员编号为纵坐标,我们得到了一个比赛日程表。

分治法——循环赛日程表_第2张图片

不难发现,图中左上角的红框部分和右下角红框部分相同,左下角蓝框和右上角蓝框部分相同,也就是说我们只需要从一半对称到另一半就可以完成这个矩阵

分治法——循环赛日程表_第3张图片

 这里最难理解的就是这个对称赋值,实质上这个赋值的顺序非常诡异,如下图所示

 分治法——循环赛日程表_第4张图片

 而且我光自己跑还不够,输入代码发现这个代码完全是错误的!m*=2应该放在i的外层使得循环n次,否则用示例代码完全不需要t循环。假设k=2,n进入循环n/2=2,t循环两次,然后m*2=2,下次进来i循环2次,m*2*2=8,完全错了。而且这两条循环语句搞得又复杂有难懂。

分治法——循环赛日程表_第5张图片

右上方矩阵=左上方矩阵+规模m

左下方矩阵=右上方矩阵对称,右下方矩阵=左上方矩阵对称 

	int mid=1;
    while (i <= m)
	{    
        //将矩阵分成左上右上左下右下四块,每块规模都是mid*mid
        //每次进入下一次分治之前左上方的矩阵都已经求出来了
		for (int j = 0; j < mid; j++)//构造右上方方阵,右上方矩阵=左上方+mid
			for (int k = 0; k < mid; k++)
				a[j][k + mid] = a[j][k] + mid;
		for (int j = 0; j < mid; j++)//对称交换构造下半部分方阵
			for (int k = 0; k < mid; k++)
			{ 
				a[j + mid][k] = a[j][k + mid];/*左下方方阵等于右上方方阵*/
				a[j + mid][k + mid] = a[j][k];//右下方方阵等于左上方方阵
			}				
			mid *= 2, i++;
	}

这样求不是简单很多吗,求出左上右上,然后对称一下,非得搞得那么麻烦,浪费时间

你可能感兴趣的:(算法设计与分析例题分析,算法)