Tennis match scheduling

前端 未结 6 2054
余生分开走
余生分开走 2020-12-12 22:06

There are a limited number of players and a limited number of tennis courts. At each round, there can be at most as many matches as there are courts. Nobody plays 2 rounds

6条回答
  •  半阙折子戏
    2020-12-12 22:48

    Python Solution:

    import itertools
    
    def subsets(items, count = None):
        if count is None:
            count = len(items)
    
        for idx in range(count + 1):
            for group in itertools.combinations(items, idx):
                yield frozenset(group)
    
    def to_players(games):
        return [game[0] for game in games] + [game[1] for game in games]
    
    def rounds(games, court_count):
        for round in subsets(games, court_count):
            players = to_players(round)
            if len(set(players)) == len(players):
                yield round
    
    def is_canonical(player_count, games_played):
        played = [0] * player_count
        for players in games_played:
            for player in players:
                played[player] += 1
    
        return sorted(played) == played
    
    
    
    def solve(court_count, player_count):
        courts = range(court_count)
        players = range(player_count)
    
        games = list( itertools.combinations(players, 2) )
        possible_rounds = list( rounds(games, court_count) )
    
        rounds_last = {}
        rounds_all = {}
        choices_last = {}
        choices_all = {}
    
    
    
        def update(target, choices, name, value, choice):
            try:
                current = target[name]
            except KeyError:
                target[name] = value
                choices[name] = choice
            else:
                if current > value:
                    target[name] = value
                    choices[name] = choice
    
        def solution(games_played, players, score, choice, last_players):
            games_played = frozenset(games_played)
            players = frozenset(players)
    
            choice = (choice, last_players)
    
            update(rounds_last.setdefault(games_played, {}), 
                    choices_last.setdefault(games_played, {}), 
                    players, score, choice)
            update(rounds_all, choices_all, games_played, score, choice)
    
        solution( [], [], 0, None, None)
    
        for games_played in subsets(games):
            if is_canonical(player_count, games_played):
                try:
                    best = rounds_all[games_played]
                except KeyError:
                    pass
                else:
                    for next_round in possible_rounds:
                        next_games_played = games_played.union(next_round)
    
                        solution( 
                            next_games_played, to_players(next_round), best + 2,
                            next_round, [])
    
                    for last_players, score in rounds_last[games_played].items():
                        for next_round in possible_rounds:
                            if not last_players.intersection( to_players(next_round) ):
                                next_games_played = games_played.union(next_round)
                                solution( next_games_played, to_players(next_round), score + 1,
                                        next_round, last_players)
    
        all_games = frozenset(games)
    
    
        print rounds_all[ all_games ]
        round, prev = choices_all[ frozenset(games) ]
        while all_games:
            print "X ", list(round)
            all_games = all_games - round
            if not all_games:
                break
            round, prev = choices_last[all_games][ frozenset(prev) ]
    
    solve(2, 6)
    

    Output:

    11
    X  [(1, 2), (0, 3)]
    X  [(4, 5)]
    X  [(1, 3), (0, 2)]
    X  []
    X  [(0, 5), (1, 4)]
    X  [(2, 3)]
    X  [(1, 5), (0, 4)]
    X  []
    X  [(2, 5), (3, 4)]
    X  [(0, 1)]
    X  [(2, 4), (3, 5)]
    

    This means it will take 11 rounds. The list shows the games to be played in the rounds in reverse order. (Although I think the same schedule works forwards and backwords.) I'll come back and explain why I have the chance.

    Gets incorrect answers for one court, five players.

提交回复
热议问题