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

问题描述:

设有n(2^k)位选手参加网球循环赛,循环赛共进行n-1天,每位选手要与其他n-1位选手比赛一场,且每位选手每天只能赛一场,试安排比赛。

举例说明:

1,当n为偶数时,循环赛一共要进行n-1天;比如,有运动员:周董,信哥,蔡依林,小七,一共4个人,可以如下安排:


运动员


第一天


第二天


第三天


周董


信哥


蔡依林


小七


信哥


周董


小七


蔡依林


蔡依林


小七


周董


信哥


小七


蔡依林


信哥


周董

可以看出,当四个人比赛的时候,要比3天才能全部比完。

2,当n为奇数时,循环赛要进行n天;如图,现有运动员:周董,信哥,蔡依林

,比赛安排表如下:


运动员


第一天


第二天


第三天


周董


信哥


蔡依林


X


信哥


周董


X


蔡依林


蔡依林


X


周董


信哥

可以看出,当n=3时,人数为奇数,并且出现轮空现象。

综上,我们可以得出一个基本结论


比赛次数=


n为偶数


n-1天


n为奇数


n天

算法描述:

按照分治策略,我们将n个选手先一分为二,每组n/2人,如果n为奇数,则(n+1)/2后分组,然后像我们一起的归并排序那样,一直分下去,直到最后只有两个人比赛。

举例说明,6个人比赛,需要比赛5天,安排如下:


1


2


3


4


5


6


2


1


5


3


6


4


3


6


1


2


4


5


4


5


6


1


3


2


5


4


2


6


1


3


6


3


4


5


2


1

回想我们的归并排序,归并排序是先分开,最后再合起来。这里也是。

我们先将6个人分成2组,每组3个人([1,2,3],[4,5,6]),然后发现3是个奇数,然后在每组中+1个虚拟人:X和Y;这样,每组就变成了4个人,然后将这4个人在除以2,我们就得到了一个两两组合的小的组。

首先来看[1,2]; [3,x]


1


2


2


1


3


X


X


3

将这两组合起来:


1


2


2


1


3


X


X


3

这样,第一天的比赛排好了,然后来排第二天的比赛。

接下来第二天让1跟3比较,这样2就只能跟x比较了。


1


2


3


2


1


3


3


X


1


X


3


2

依此类推,第三天,让1跟x比较,2跟3比较:


1


2


3


x


2


1


x


3


3


X


1


2


X


3


2


1

这里要得到3个选手的比赛安排,所以,我们将假象的X去掉,并将它的位置以*代替:


1


2


3


*


2


1


*


3


3


*


1


2

然后我们也按照这个规律,安排[4,5,6]的日程,得到表格


4


5


6


*


5


4


*


6


6


*


4


5

将前3天的日程安排合并起来:


1


2


3


*


2


1


*


3


3


*


1


2


4


5


6


*


5


4


*


6


6


*


4


5

我们可以看到,第一天,3和6都空闲,可以让他们比赛;第二天,2和5都空闲,可以让他们比赛;第三天,1和4空闲,让他们相互比赛;

所以,上表重新安排,得到前3天的日程安排表:


1


2


3


4


2


1


5


3


3


6


1


2


4


5


6


1


5


4


2


6


6


3


4


5

这样,我们就比较过了[1,2,3]和[4,5,6].

然后循环下,得到:


[1,2,3]& [5,6,4]


[1,2,3]& [6,4,5]

安排三天的比赛:


1


2


3


5


2


1


6


3


3


4


1


2


5


6


4


1


6


5


2


4


4


3


5


6


1


2


3


6


2


1


4


3


3


5


1


2


6


4


5


1


4


6


2


5


5


3


6


4

选取黄色的日程安排,加入到前3天的日程安排表中:


1


2


3


4


5


6


2


1


5


3


6


4


3


6


1


2


4


5


4


5


6


1


3


2


5


4


2


6


1


3


6


3


4


5


2


1

如果n恰好等于2^k,那么,安排日程表就变得比较简单了,我们先安排两位选手,


1


2


2


1

安排4位选手:


1


2


3


4


2


1


4


3


3


4


1


2


4


3


2


1

这时候,我们先按照两个选手的,将1和2的安排填好,然后填写左下角的安排,然后将左下角的元素抄到右上角,最后将左上角的元素抄到右下角。

小结:

分治法在将大问题一步一步两两分,直到划分成可以解决的小问题时,求出这些小问题的解,然后再将小问题合成大问题的解,但是前提是这些小问题在求解是不受到其他小问题的解的影响的。

时间: 2025-01-17 11:20:39

分治法——循环赛日程安排问题的相关文章

循环赛日程安排问题

问题描写叙述:    设有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的奇数位置上. 接下来将队伍一分为二,奇数为一组

循环赛日程表 分治法

循环赛日程表 分治法 采用分治法, 逐步产生结果, 将 左上角的数字,拷贝到 右下角, 右上角的数字,拷贝到 左下角. 本程序以偶数计算,如果是奇数的话,那么就多增加一个,做轮空处理. // 采用分治法 #include <iostream> #include <cstdio> using namespace std; const int M = 1<<10; int a[M][M]; void getTable(int k) // 2^k { int n = 1<

分治法

分治法的基本思想是将一个规模为n的问题分解为k个规模较小的子问题,这些子问题相互独立且与原问题相同.递归的解这些子问题,然后将各子问题的解合并得到原问题的解. 分治法所能解决的问题一般具有以下几个特征: 1) 该问题的规模缩小到一定的程度就可以容易地解决 2) 该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质. 3) 利用该问题分解出的子问题的解可以合并为该问题的解: 4) 该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子子问题. 分治法的基本步骤:分治法在

分治法-汉诺塔问题

一 基本概念 分治法,顾名思义分而治之的意思,就是把一个复杂的问题分成两个或很多其它的同样或相似的子问题,再把子问题分成更小的子问题--直到最后子问题能够简单的直接求解,原问题的解即子问题的解的合并. 二基本思想及策略 分治法的设计思想是:将一个难以直接解决的大问题,切割成一些规模较小的同样问题,以便各个击破,分而治之. 分治策略是:对于一个规模为n的问题,若该问题能够easy地解决(比方说规模n较小)则直接解决,否则将其分解为k个规模较小的子问题,这些子问题互相独立且与原问题形式同样,递归地解

分治法-最近距离问题Java实现

分治算法,有很多典型的问题,如最近点问题.线性选择问题.整数划分问题.大整数成绩问题.棋盘覆盖问题.循环赛日程表.二分搜索.Strassen矩阵乘法.汉诺塔等.准备花些时间逐个解决这些问题,并用Java实现,从最近点问题开始.网上找到一些代码,标题如"java 用蛮力法和分治法求解最近对有关问题",虽然体现了分治,但划分不够彻底,因此我重新对其进行了实现. 一.基本思想及策略: 首先,说说分治的思想.分治, "分而治之",就是把一个复杂的问题分成两个或更多的相同或相

分治法、动态规划、回溯法、分支界限法、贪心算法

转:http://blog.csdn.net/lcj_cjfykx/article/details/41691787 分治算法一.基本概念 在计算机科学中,分治法是一种很重要的算法.字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并.这个技巧是很多高效算法的基础,如排序算法(快速排序,归并排序),傅立叶变换(快速傅立叶变换)…… 任何一个可以用计算机求解的问题所需的计算时

算法复习笔记(分治法、动态规划、贪心算法)

分治法 动态规划 贪心算法 分治法 分治法的基本思想是将一个规模为n的问题分解为k个规模较小的问题,这些子问题互相独立且与原问题相同(所以可以递归).递归地解这些子问题,然后将各个子问题的解合并得到原问题的解.它的一般算法设计模式如下: divide-and-conquer(P) { //|P|表示问题的规模,n0表示阈值,当规模不超过n0时,问题容易解出,不必分解 if(|P|<=n0) adhoc(P); //将P分解成子问题 divide P into smaller subinstanc

算法学习笔记系列——分治法

一.基本概念 在计算机科学中,分治法是一种很重要的算法.字面上的解释是"分而治之",就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题--直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并.这个技巧是很多高效算法的基础,如排序算法(快速排序,归并排序),傅立叶变换(快速傅立叶变换). 二.基本思想及策略 分治法设计思想:将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之. 分治策略是:对于一个规模为n的问题,若该

LeetCode刷题总结-双指针、位运算和分治法篇

本文总结LeetCode上有关双指针.位运算和分治法的算法题,推荐刷题总数14道.具体考点分析如下图: 一.双指针 1.字符串和数组问题 题号:424. 替换后的最长重复字符,难度中等 题号:828. 独特字符串,难度困难 题号:923. 三数之和的多种可能,难度中等 2.实际场景应用问题 题号:826. 安排工作以达到最大收益,难度中等 3.元素对问题 题号:986. 区间列表的交集,难度中等 二.位运算 1.字符串和数组问题 题号:137. 只出现一次的数字 II,难度中等 题号:318.