3

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

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 个 .. 哎呀

数字是团队。每支球队都需要与每支球队比赛一次。赛程将设置为每支球队每周只打一场比赛。时间表需要设置几个星期,以允许在没有球队每周比赛超过一次的情况下进行所有比赛。

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

$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;
}

所以这没有用,我把它复杂化了,超出了它应该的程度,我不能再解决这个问题了。任何帮助,即使它意味着重新开始,将不胜感激!

4

5 回答 5

1

也许这段代码可以解决您的问题,它虽然没有想象中的那么优雅,但它似乎可以工作。您应该知道安排游戏的工作原理;)

或许你需要注意一下安排播放器forDays。仅当两名玩家当天都没有安排比赛时,它才会将各种比赛放在一天中。另一个函数只是为了使代码更具可读性(并涵盖了安排播放器forDays中的一对故障)

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);
于 2009-08-04T11:33:22.963 回答
1

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

于 2009-08-04T09:17:44.050 回答
0

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

于 2009-08-05T22:41:32.763 回答
0

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

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

那应该很容易。然后你只需遍历这个数组,把游戏放在第一行没有任何球队在玩的地方。可能会有更好更快的解决方案,但这是我想到的第一个解决方案,我认为它很容易编写。

于 2009-08-04T09:10:22.283 回答
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/>";
}
于 2010-12-04T00:44:47.120 回答