解决方案 »

  1.   

    $a = array('A1', 'A2', 'A3', 'A4', 'A5', 'A6');berger_method($a);function berger_method($ar) {
      if(count($ar) %2) $ar[] = ' ';
      $t = array_merge(range(1, count($ar)-1), range(1, count($ar)-1));  $len = count($ar);
      $m = range(1, $len);
      $lun = 0;
      $last = 0;
      $k = $len <= 4 ? 1 : ($len - 4) / 2 + 1;
      while($lun++ < $len-1) {
        $s = array_values($m);
        echo "== $lun ==\n";
        for($i=0; $i<$len/2; $i++) printf("%s -- %s\n", $ar[$s[$i]-1], $ar[$s[$len-1-$i]-1]);
        echo "\n";    list($m[0], $m[$len-1]) = array($m[$len-1], $m[0]);
        for($i=0; $i<$k; $i++) {
          if($m[++$last % $len] == $len) $last++;
        }
        $n = $last %= $len;
        for($i=1; $i<$len; $i++) {
          if(($m[$n]) == $len) $n = ($n + 1) % $len;
          $m[$n] = $i;
          $n = ($n + 1) % $len;
        }
      }
    }
    == 1 ==
    A1 -- A6
    A2 -- A5
    A3 -- A4== 2 ==
    A6 -- A4
    A5 -- A3
    A1 -- A2== 3 ==
    A2 -- A6
    A3 -- A1
    A4 -- A5== 4 ==
    A6 -- A5
    A1 -- A4
    A2 -- A3== 5 ==
    A3 -- A6
    A4 -- A2
    A5 -- A1
    这是单循环的
    双循环将 14 行的
    while($lun++ < $len-1) {
    改作
    while($lun++ < ($len-1)*2) {
    就可以了真难为了 贝格尔 弄出这么个编排法
    绕了5、6个小时才把算法理顺
      

  2.   


    非常感谢 版主大人  版主果然厉害! 但是 还有有问题的 版主 求救啊!晚上 都睡不着 因为这个算法。是这样的  选择一天一场   然后 根据 参赛队伍 出现总轮数 然后一天一场的 意思 是 每个球队 每天 一场比赛 比赛都是分 主场和客场的 
    您这个 只是每个队 又一场比赛  比如 A1 -- A6  这是 主场:客场   但是没有  反过来的  A6 VS A1
    这个 好像不只是  反过来 那么简单!
      

  3.   

    比如 第一天  A1-A2  A3-A4  A5-A6  
    第二轮 可能是A2-A1  A4-A3 A6-A5 
    就是每个队 跟对手 都有两场比赛
    但是 主场一次 客场一次!
      

  4.   

    当然不是那么简单,否则赛事组委会也太轻松了
    目前世界性单循环赛都采用“贝格尔编排方法”,就是我介绍的这种。当然你也可以采用“逆时针轮转方法”,虽然存在一些问题,但算法要简单的多我也搜索了双循环赛的编排方法,但遗憾的是无法找到。
    于是我做了一下测试,结果发现把单循环的算法推广到双循环时。成功的概率只有万分之36,这也就是都不愿公开双循环编排方法的原因吧。
    $a = array('A1', 'A2', 'A3', 'A4', 'A5', 'A6');
    $last = berger_method($a);set_time_limit(60);
    $x = 10000;
    $double = array();
    do {
      shuffle($a);
      $r = array_merge($last, berger_method($a));
      $res = array_combine($a, array_fill(0, count($a), array('场数' => 0, '主场' => 0, '客场' => 0)));  foreach($r as $item) {
        $res[$item['主场']]['场数']++;
        $res[$item['主场']]['主场']++;
        $res[$item['客场']]['场数']++;
        $res[$item['客场']]['客场']++;
      }
      if(! array_filter($res, function($v) { return $v['主场'] != $v['客场']; })) {
        $double[] = join(',', $a);
      }
    }while($x--);
    print_r(array_values(array_unique($double)));
    可知,当初始序列为 A1,A2,A3,A4,A5,A6 时
    第二个单循环的初始序列必须为下列之一时,才能要求    [0] => A4,A5,A6,A2,A3,A1
        [1] => A5,A6,A4,A1,A2,A3
        [2] => A5,A4,A6,A3,A2,A1
        [3] => A4,A6,A5,A3,A1,A2
        [4] => A5,A6,A4,A2,A3,A1
        [5] => A6,A5,A4,A1,A2,A3
        [6] => A6,A5,A4,A1,A3,A2
        [7] => A6,A4,A5,A1,A2,A3
        [8] => A4,A6,A5,A2,A3,A1
        [9] => A5,A4,A6,A2,A3,A1
        [10] => A6,A5,A4,A2,A1,A3
        [11] => A5,A4,A6,A1,A2,A3
        [12] => A4,A6,A5,A2,A1,A3
        [13] => A4,A5,A6,A1,A2,A3
        [14] => A6,A5,A4,A3,A2,A1
        [15] => A5,A4,A6,A1,A3,A2
        [16] => A6,A5,A4,A3,A1,A2
        [17] => A4,A5,A6,A3,A2,A1
        [18] => A6,A4,A5,A2,A1,A3
        [19] => A4,A5,A6,A2,A1,A3
        [20] => A5,A6,A4,A2,A1,A3
        [21] => A6,A4,A5,A3,A2,A1
        [22] => A5,A6,A4,A3,A1,A2
        [23] => A4,A6,A5,A1,A2,A3
        [24] => A5,A6,A4,A3,A2,A1
        [25] => A4,A6,A5,A1,A3,A2
        [26] => A6,A4,A5,A2,A3,A1
        [27] => A5,A4,A6,A2,A1,A3
        [28] => A4,A6,A5,A3,A2,A1
        [29] => A4,A5,A6,A3,A1,A2
        [30] => A5,A4,A6,A3,A1,A2
        [31] => A6,A4,A5,A3,A1,A2
        [32] => A6,A4,A5,A1,A3,A2
        [33] => A5,A6,A4,A1,A3,A2
        [34] => A6,A5,A4,A2,A3,A1
        [35] => A4,A5,A6,A1,A3,A2