排序列表有多个限制

时间:2015-02-19 20:10:33

标签: python python-2.7

有6名玩家在双人系统运动中竞争,我试图找到一种匹配最佳对的算法。

限制如下:玩家无法播放位于“无法播放”列表中的玩家,并且需要根据“最佳播放”列表播放最佳匹配。因此,下一轮的玩家1最佳匹配是玩家3,最差的是玩家4.

我想出了一个拥有最佳配对系统的聪明方法。

Player 1: Cannot Play(1,2,6) ; Best Play(3,5,4)  
Player 2: Cannot Play(2,1,5) ; Best Play(4,3,6)  
Player 3: Cannot Play(3,2,4) ; Best Play(1,5,6)  
Player 4: Cannot Play(4,3,6) ; Best Play(2,6,1)  
Player 5: Cannot Play(5,3,6) ; Best Play(3,4,1)  
Player 6: Cannot Play(6,4,5) ; Best Play(2,1,3)

请注意,在此示例中,您可以在P1到P3之间快速分配,然后在P2到P4之间快速分配,但是由于P5无法播放P6,您会卡住。

编辑:我到目前为止尝试了以下内容。但是,我试图弄清楚问题的整体方法,而不是我的代码的解决方案。我在代码中的问题是,有时最后一对不能对抗彼此,我没有为它们分配:

swissPair=[]
cannot_play_against=[]
DB = psycopg2.connect("dbname=tournament")
c = DB.cursor()

standings = playerStandings()

# Assigning pairs
for player in standings:

    # Building a list of players player[0] won't be playing:
    # 1. Players already played 2. Players that are already assigned

    c.execute("SELECT loser from matches where winner=" + str(player[0]))
    lost_against = list(c.fetchall())
    c.execute("SELECT winner from matches where loser=" + str(player[0]))
    won_against = list(c.fetchall())
    already_assigned = [(i[0],) for i in swissPair] + [(i[2],) for i in swissPair]
    cannot_play_against = set(won_against + lost_against + already_assigned)

    # Making sure the player is not already assigned
    if (player[0],) not in already_assigned:

        # Creating a table sorted by (absolute winnings-player winnings)
        # By doing it we find opponents at the player's level
        c.execute("SELECT id, name, wins, abs(wins-" + str(player[2]) + ") from standings order by abs")
        list_by_distance = list(c.fetchall())
        # Removing those who can't play the player and the player himself
        can_play_against = [z for z in list_by_distance if z[:1] not in cannot_play_against and z[0]<>player[0]]

        if len(can_play_against)>0: swissPair.append((player[0],player[1],can_play_against[0][0],can_play_against[0][1]))  

        # In case all the pairs has been assigned: break
        if len(swissPair) == len(standings)/2: break

DB.close()
return swissPair

1 个答案:

答案 0 :(得分:0)

忽略代码而只是谈论过程:
如果以后没有选择,您可以尝试手动分解先前的配对;例如:

  1. P1匹配P3,分配。
  2. P2匹配P4,分配。
  3. (P3已经分配。)
  4. (已经分配了P4。)
  5. P5没有候选人 - 最佳候选人是P3。打破P1 / P3配对,新配对是P5 / P3。 P1再次未分配。
  6. P6匹配P1,分配。
  7. 我不确定这个过程是否可以保证在所有可能的情况下完成,可能必须对其进行扩展以跟踪之前的对,并防止它们重新创建到阻止周期发生。