首页 > 代码库 > 分治法——循环赛日程安排问题
分治法——循环赛日程安排问题
问题描述:
设有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的安排填好,然后填写左下角的安排,然后将左下角的元素抄到右上角,最后将左上角的元素抄到右下角。
小结:
分治法在将大问题一步一步两两分,直到划分成可以解决的小问题时,求出这些小问题的解,然后再将小问题合成大问题的解,但是前提是这些小问题在求解是不受到其他小问题的解的影响的。
分治法——循环赛日程安排问题