具有大量参与者的锦标赛的调度算法?

时间:2017-02-05 06:44:56

标签: algorithm combinatorics

说,我们有100多名参赛者和3个获奖名额。我需要安排尽可能少的比赛才能找到3名获胜者。其他地方根本不重要。 循环算法看起来不必要昂贵。

这是我的解决方案:

const match = (a, b) => {
  if (!a || !b) {
    return {winner: a || b}
  }
  // simulate match
  const winner = Math.random() > 0.5 ? a : b
  console.log(`Match between ${a} and ${b}: ${winner} wins`)
  return {winner, looser: winner === a ? b : a}
}
let participants = {
  // [id]: {win: Number, loose: Number}
}
let participantsNumber = 100
let n = 0

// create random participants
while(n < participantsNumber) {
  n++
  participants[String(n)] = {win: 0, loose: 0}
}

let round = 0
while(participantsNumber > 3) {
  let odd = true
  let matches = []
  _.map(participants, (winLooseStats, id) => {
    if (odd) {
      odd = false
      matches.push({player_1: id})
    } else {
      odd = true
      let opponentFound = false
      matches.map(match => {
        if (!match.player_2 && !opponentFound) {
          opponentFound = true
          match.player_2 = id
        }
      })
    }
  })
  console.log('matches', matches)
  // run matches
  matches.forEach(({player_1, player_2}) => {
    const {winner, looser} = match(player_1, player_2)
    participants[winner].win++
    if (looser) {
      participants[looser].loose++
    }
  })

  // remove those, who has lost 3 times
  _.map(participants, ({win, loose}, id) => {
    if (loose > 2) {
      console.log(`Player ${id} has lose 3 times`)
      delete participants[id]
      participantsNumber--
    }
  })
  round++
  console.log(`Round ${round} complete. ${participantsNumber} players left`)
}

console.log(`3 champions: ${_.map(participants, (wl, id) => id).join(', ')}`)

JSFIDDLE

每100名参与者约12轮。是否可以减少轮数?

1 个答案:

答案 0 :(得分:0)

问题有点模糊,但我认为你的规则如下:

  • 任何一对队员都不会超过一场比赛。如果A击败B,我们假设A总是击败B。
  • 我们假设一个传递属性:如果A击败B和B击败C,我们可以假设A击败C并且我们不必安排匹配来找到它。

假设这是正确的,并且您有n个玩家,那么您可以使用标准single elimination tournament以最佳方式解决此问题,以找到获胜者和第二名。要找到第三名,你必须在两个没有进入最后一场比赛的人之间再添一场比赛。