代码之家  ›  专栏  ›  技术社区  ›  Banana

给每个列表分配一个不在该列表中的数字

php
  •  -2
  • Banana  · 技术社区  · 7 年前

    我的标题措辞可能更好。我将从一个我通常遇到的问题开始,解释一下大局,然后归结到确切的问题。

    我有一个网络应用程序来主持比赛,我想其中一个很酷的功能就是分配参赛者的曲目(所以不仅要计算和提供用户界面,还要确定球员应该在哪个曲目上比赛(如果你想想象一个曲目,可以想象一个保龄球道)。问题是,如果球员上一场比赛或之前的比赛都在同一条赛道上打过,他就不能在同一条赛道上比赛(但如果在赛道上打得更远,他就可以在同一条赛道上比赛)。

    当参赛者互相比赛时,我的第一个想法(也是目前唯一的想法)是遍历每对选手,检查他们在哪个曲目上比赛,并将它们添加到名为 playedTracks .

    假设这个函数已经完成,并且正确地返回一个数组 播放机架 最大尺寸的 4 (四是两名选手至少打了三回合,但其中一名选手没有在同一条赛道上打过比赛):

    function getPlayedTracks($resultId,$opponentResultId,$currentRound){
        //Returns the list of tracks on which the pair has played on!
        $playedTracks = [];
        if ($currentRound == 1){
            //No tracks to pick from
            return [];
        }
        else if ($currentRound == 2){
            //One track to pick from
            $oneBehind = 1;
        }
        else{
            //Pick from two tracks
            $oneBehind = $currentRound - 1;
            $twoBehind = $currentRound - 2;
        }
        return $playedTracks,
    }
    

    现在我坐在一个循环中(正如我所提到的,我正在迭代一对玩家),我有一对玩家和他们玩过的曲目。我还有一组音轨要分配,假设我有带数字的音轨 1,2,3,4,5 $playedTracks 返回 [1,2,3] . 所以选择是 4 or 5 . 我来挑 . 当循环向前迭代时 $播放机架 在某个时候可能会有一条赛道需要分配,但是他们已经在过去的两场比赛中都在这条赛道上比赛了。

    我不确定我的方法是否正确,也许我应该考虑一个球员一个球员的接近,而不是一对球员。有没有人遇到过类似的问题,或者对这件事能说些有用的话?

    奇怪的是,这是循环部分(是的,mysql扩展不推荐使用,我知道):

    while ($player = mysql_fetch_assoc($allTourneyPlayers)){
        $resultId = $player['resultid'];
        if (in_array($resultId,$checkedResults)){
            //Player already has it's track numbers from opponent
            continue;
        }
        $getCurrentRound = mysql_query("SELECT * FROM roundresults WHERE resultid='$resultId' AND roundNr = '$currentRound'",$connection);
        $opponentTpId = $getCurrentRound['opponentid'];
        $getOpponentDetails = mysql_query("SELECT * FROM tourneyplayers WHERE tpid = '$opponentTpId' AND tourneyid='$tourneyid'",$connection);
        $opponentResultId = $getOpponentDetails['resultid'];
        $playedTracks = getPlayedTracks($resultId,$opponentResultId,$currentRound);
        //Add opponent and current player to checked results!
        $checkedResults[] = $opponentResultId;
        $checkedResults[] = $resultId;
    }
    
    1 回复  |  直到 7 年前
        1
  •  0
  •   Banana    7 年前

    如果下次有人遇到麻烦就把答案贴出来。

    曲目列表 $listOfTracks = [1,2,3,4,5] . 这些都是铁轨。

    每个对的可用磁道可以添加到数组中(其中索引指对):

    $availableTracks = [[1,4],[3,5],[2,3,5],[1,2],[2,4]]
    

    此数组可以可视化为树。第一个包含所有磁道号的组合是一个合适的组合(在上面的例子中,它可以是 1,3,5,2,4 4,3,5,1,2 取决于选择哪种算法来遍历树。显然,每种解决方案都可能有一个或两个以上的解决方案,但任务并不是只找到第一个。

    遍历树的算法之一是“choose left”,如果可能的话,总是选择最左边的节点(基于前面的例子 $availableTracks = [[1,4],[3,5],[2,3,5],[1,2],[2,4]] :

    Current node [1,4], Select 1, move downwards - $selectedNumbers = [1]
    Current node [3,5], Select 3, move downwards - $selectedNumbers = [1,3]
    Current node [2,3,5], Select 2, move downwards - $selectedNumbers = [1,3,2]
    Current node [1,2], 1 and 2 are only available nodes, both are used, move upwards and continue with different node.
    Current node [2,3,5], 2 wasnt suitable, 3 is not suitable (as already used), Select 5, move downwards - $selectedNumbers = [1,3,5].  
    Current node [1,2], 1 is not suitable (as already used), Select 2, move downwards - `$selectedNumbers = [1,3,5,2]`
    Current node [2,4], 2 is not suitable (as already used), Select 4, array has reached the same length as number of pairs, found suitable.
    Final list: `$selectedNumbers = [1,3,5,2,4]`
    
    推荐文章