循环赛问题

来源:互联网 发布:js div内容 实体 编辑:程序博客网 时间:2024/04/30 13:43

源于论坛一个帖子,从一个各元素不同的偶数个元素数组(比如[1 2 3 4 5 6])中任取两个元素的组合,然后将这些所有两个元素的组合分成若干组,每组都能重新组成新数组,而这个新数组正好与原来数组相同,问当这个偶数数组是1-100时,一共能排列成多少种,并一一列举出来。

论坛回复有两种比较好的方法,我只看懂了一种,发下:
比如数组1-6,[1 2 3 4 5 6],任意取两个元素一共有12,13,14,15,16,23,24,25,26,34,35,36,45,46,56十五种(6*5/2),将这十五个新元素可以不重复的组成5组新数组和原来一样,他们是:[12 34 56]、[13 25 46]、[14 26 35]、[15 24 36]、[16 23 45]——正好全部用完十五种不重复;

 

这其实是一个循环赛问题,解决办法如下:

1、取1、n,2、n-1...分别形成组合

2、固定一个元素,使其他的元素做循环左移或右移,移动一次后再按1进行处理,直循环完。

 

举例如下:

1: 123456->1:6,2:5,3:4

固定 1,循环其他

2: 162345->1:5,6:4,2:3

3: 156234->1:4,5:3,6:2

4: 145623->1:3,4:2,5:6

5: 134562->1:2,3:6,4:5

于是得到一种组合方式,按以下规则可以得到其他组合

法1: 使1与其他5个数互换,可以得到五种

法2: 除1外的其他5个数与相临数互换,可以得到五种

法3: 除1外的其他5个数与间隔一个的数互换,又可以得到五种。

因为是循环数,间隔再大时与以上重复。

于是共有15种不同的组合

还有这么一个算法,没看懂,有机会再研究一下:             

花了一天时间看了一下算法2 ,稍微有点懂了。
第二个算法中ci++ <=> ci = 2*j +(i-j)+1,而ci=ci-(m-j) <=> ci=2*j-1。这里将ci代入前式,并注意到两者的i差1便可以得出。
这种表达式变换对理解程序很有帮助。

设编号分别为1..n的n个人分组,其中n-2个人定了,则分组方式也就定了。取第1人与他人结合,
有1:2,1:3,...,1:n 共n-1组,每组两个编号的“和”从3..1+n,连续,对n-1取模得0..n-1,没有重复,正好n-1组。
现在不考虑n,任取两个数求其和并对n-1取模,设其结果为a则放到第a组,如果可得到n-1组,其中每组有n-2个值,这样就确定了分组。

如   12 35 46  :3 
     13 45 26  :4
     14 23 56  :5
     15 24 36  :6
     16 25 34  :7
第二个算法便是在此基础上分组的,不同的是它可以直接将每组最后一个组合(与n结伴的人)直接分到相应的组中。
  其实n与1地位相当,因为n mod(n-1)=1,因此每组最后一个组合由与n结伴的人的编号确定,由程序可以看出,它们被分到

  (2*j) mod (n-1)这一组,其中j等与n结伴的人的编号-1。  

 

 

原创粉丝点击