从平面数组生成循环赛时间表

问题描述 投票:0回答:5

我有一个长度未知的数组,它总是有可均匀整除的值,例如:

print_r($initialarray);

Array ( [0] => 30 [1] => 31 [2] => 32 [3] => 33 [4] => 34 [5] => 35 ) 

我需要创建集合:

Set 1: 30 v 35; 31 v 34; 32 v 33;

Set 2: 30 v 34; 31 v 33; 32 v 35;

Set 3: 30 v 33; 31 v 32; 34 v 35;

Set 4: 30 v 32; 33 v 34; 31 v 35;

Set 5: 30 v 31; 32 v 34; 33 v 35; 

值的顺序除以 v 表示它们是一个集合。集合中值的顺序并不重要(我随机地将它们放在一起)。正如您所看到的,任何其他集合或同一集合中都不能有重复的集合匹配。

我尝试了很多不同的方法来想出一些可行的方法。 我得到的最接近的是将初始值放入包含所有可能的有效匹配的级联数组中:

Array ( [0] => Array ( [0] => 35 [1] => 31 ) [1] => Array ( [0] => 34 [1] => 31 ) [2] => Array ( [0] => 33 [1] => 31 ) [3] => Array ( [0] => 32 [1] => 31 ) )

Array ( [0] => Array ( [0] => 35 [1] => 32 ) [1] => Array ( [0] => 34 [1] => 32 ) [2] => Array ( [0] => 33 [1] => 32 ) )

Array ( [0] => Array ( [0] => 35 [1] => 33 ) [1] => Array ( [0] => 34 [1] => 33 ) )

Array ( [0] => Array ( [0] => 35 [1] => 34 ) ) 

这些值是一个名为 $sched 的数组中的数组。 我在数组中漏掉了 30 个..哎呀

数字是团队。每支球队需要与每支球队比赛一次。赛程安排将确保每支球队每周只打一场比赛。 赛程需要在几周内制定,以允许所有比赛都可以进行,而没有一支球队每周比赛超过一次。

我已经使用了排列函数,这就是我如何想出上面的数组,它没有相同的匹配。我现在需要弄清楚如何输出上面的集合中所示的时间表。 (请记住,只要没有球队在同一盘中比赛两次,示例的顺序并不重要)

$count = count($initialarray);
$recount = $count -1;
for($u=0; $u < $count;$u++){
    for($d=0;$d<$recount;$d++){
         $vs[$u][$d] = $sched[$d][$u];
    }
$recount -= 1;
}

所以这不起作用,我让事情变得更加复杂,超出了应有的范围,我无法再专注于这个问题了。任何帮助,即使这意味着重新开始,我们都将不胜感激!

php arrays multidimensional-array unique permutation
5个回答
1
投票

也许这段代码可以解决您的问题,它并不那么优雅,但似乎可以工作。 你应该知道安排游戏是有效的;)

也许你需要注意arrangePlayerforDays。仅当双方球员当天都没有安排比赛时,它才会将各种比赛放在一天中。 另一个函数只是为了使代码更具可读性(并覆盖 arrangePlayerforDays 中的一对小故障)

function gamePrettyPrint($gamesOnADay, $glue) {
  $result=array();
  foreach ($gamesOnADay as $currentGame) 
      $result[]=join($glue,$currentGame);
  return $result;
}

function arrangeGamesOnAday($day) {
  $result=array();
  for ($k=0, $limit=count($day); $k<$limit; $k+=2)
      $result[]=array($day[$k+1], $day[$k]);
  return $result;
}

function arrangeGames($players) { 
  for ($i=0, $limit=count($players); $i < $limit; $i++) 
    for ($j=$i+1; $j<$limit;$j++) 
      $games[]=array($players[$i], $players[$j]);
  return $games;
}

function calculateTournamentDuration($players) {
  return  count($players)-1; // (n!)/(2!*(n-2)!) * (1/n)
}

function arrangePlayerforDays($games, $days) {
  $mem = array_pad(array(),$tournamentDays,array());
  for ($k=0;count($games);$k++)
    if ((array_search($games[0][0],$mem[$k%$days])=== false)  and
        (array_search($games[0][1],$mem[$k%$days])=== false))
      list($mem[$k%$days][], $mem[$k%$days][]) = array_shift($games);
  return ($mem);
}

function scatterGamesOnCalendar($games, $tournamentDays) {
  $days=arrangePlayerforDays($games, $tournamentDays);
  $calendar=array_map('arrangeGamesOnAday',$days);
  return $calendar;
}

//  $initialArray = array('a','b','c','d','e','f','g','h');
$initialArray = array(30,31,32,33,34,35);

$games= arrangeGames($initialArray);
$tournamentSpan = calculateTournamentDuration($initialArray);
$calendar = scatterGamesOnCalendar($games, $tournamentSpan);

while ($day=array_shift($calendar))
  $prettyCalendar[]=gamePrettyPrint($day,' v ');

print_r($prettyCalendar);

0
投票

你可以构建一个数组,其中包含每个“游戏”,所以它就像这样

0 => 30 v 35
1 => 31 v 34
2 => 32 v 33

那应该很容易。然后你只需浏览这个数组并将比赛放在第一行,那里没有球队正在比赛。可能有更好更快的解决方案,但这是我首先想到的,我认为它写起来很简单。


0
投票

我没有直接的答案,但看起来你可能需要一点图论。 http://en.wikipedia.org/wiki/Tournament_%28graph_theory%29


0
投票
$team = array( 1 => 30 , 2 => 31 , 3 => 32 , 4 => 33 , 5 => 34 , 6 => 35 );

$numplayers = count($team);
if ($numplayers % 2 != 0) $numplayers++; 
for ($round = 0;$round < $numplayers - 1;$round++) {
    echo 'Set ' . ($round+1) . ":\n\n{$team[1]}-";
    for ($i = 0;$i < $numplayers-1;$i++) {
        if ($i % 2 == 0) {
            $player = ($numplayers-2) - ($i/2) - $round;
        } else {
            $player = ((($i-1)/2) - $round);
        }
        if ($player < 0) $player += $numplayers - 1;
        echo $team[$player+2];
        echo ($i % 2 == 0) ? "\n" : '-';
    }
    echo "\n\n<br/>";
}

-1
投票

这个问题有你想要的答案吗?

© www.soinside.com 2019 - 2024. All rights reserved.