【问题标题】:Create a schedule where a group of people all talk to each other - with restrictions创建一个时间表,让一群人互相交谈 - 有限制
【发布时间】:2020-12-05 23:26:35
【问题描述】:

问题陈述

我想实现以下目标: (例如可以用来为学生组织某种快速约会活动)

创建一个时间表,以便人们可以一对一地相互交谈,并与小组中的每个成员交谈。 但有限制。

  • 输入:人员列表。 (例如 30 人)
  • 限制:有些人不应该互相交谈(例如,他们彼此认识)
  • 输出:配对列表(分成会话)只需一个解决方案即可,无需了解所有可能的结果

示例

例如。 4人一组

  1. 约翰
  2. 史蒂夫
  3. 马克
  4. 梅丽莎

限制:约翰 - 梅丽莎 -> 否

结果

第一节

  • 约翰 - 史蒂夫
  • 马克 - 梅丽莎

第二场

  • 约翰-马克
  • 史蒂夫 - 梅丽莎

第三节

  • 史蒂夫-马克

John 和 Mellisa 不会加入第三节,因为这是限制。

问题

有没有办法使用 Python 甚至 excel 来解决这个问题?

我特别在寻找一些指示如何调用这个问题,因为我认为这是一些我应该寻找一些求解器吗?动态规划等?

【问题讨论】:

  • 这已经很有趣了。如何对其添加限制。例如,来自同一个国家的球队不应该互相比赛。我确实只需要一个解决方案,而不是一个完美的解决方案。
  • 您可以检查算法可能生成的每一对,如果不应该有一对,则不生成。
  • 显然需要进行会话,直到每个人都与每个可能的合作伙伴配对一次?解决方案是否需要优化? (即,最少的会议数量和最少的等待人数,直到最后,每个人都能见到每个可能的候选人?)
  • 非常有帮助的评论。我想限制会话的数量,这样我就会有一些人不会互相交谈,但没关系,截止时间会相当随机。

标签: python algorithm dynamic-programming


【解决方案1】:

这是一个相当幼稚的实现:

from itertools import combinations
from typing import Set, List, Generator


def generate_sessions(people: Set, excl: List[Set]) -> Generator[List[Set], None, None]:
    # all the pairings you need are all possible pairings, except the exclusions
    needed_pairings = [set(pair) for pair in combinations(people, 2)]
    for pair in excl:
        needed_pairings.remove(pair)

    # while there pairing that haven't happened yet
    while needed_pairings:
        # each session starts empty
        session = []
        # keep track of all people still available for this session
        available = set(people)
        # create an iterator, so we can loop over the needed pairings
        iter_needed_pairings = iter(needed_pairings)
        # as long as there are more than 2 people still waiting and there's a pair left in the needed pairings
        while (len(available) > 1) and (pair := next(iter_needed_pairings, False)):
            # are both people in the pair in the group of available people?
            if available.intersection(pair) == pair:
                # then they can meet in this session
                session.append(pair)
                # and they're no longer available
                available -= pair
        # once we have a session, remove the pairs in it from the pairings still needed
        for pair in session:
            needed_pairings.remove(pair)
        # yield the session
        yield session


print(list(generate_sessions(people={'John', 'Steve', 'Mark', 'Melissa'}, excl=[{'John', 'Melissa'}])))

结果(可能会因集合的无序性质而有所不同):

[[{'John', 'Mark'}, {'Melissa', 'Steve'}], [{'John', 'Steve'}, {'Melissa', 'Mark'}], [{'Mark', 'Steve'}]]

这会生成会话,直到每个人都见面为止。您可以从生成器中获取next(),直到您有足够的会话。这种方法的唯一缺点是它可能会在一个有更多人开会的会话之前找到几个人正在等待的会话。您可以通过按长度对会话进行排序来解决这个问题,但这当然意味着生成所有会话。

编辑:我添加了输入信息,以明确预期的类型是什么,但它当然不需要它来工作。

【讨论】:

    【解决方案2】:

    你给的信息挺大方的,你有一组所有的学生,还有一组no-go pair(因为你自己说的,也好解释,就说这是一组pair认识的学生)。所以我们可以遍历我们的学生列表创建随机配对,只要它们不存在于我们的 no-go 集中,然后用它们扩展我们的 no-go 集,并递归剩余的学生,直到我们无法创建任何配对不存在于禁止组中(我们有配对,因此每个学生都遇到了所有学生)。

    【讨论】:

    • 您的方法不处理将两个配对添加到包含同一个人的会话的情况。例如,John 不应在同一会话中同时遇到 Mark 和 Steve。
    猜你喜欢
    • 2010-09-09
    • 1970-01-01
    • 1970-01-01
    • 2018-11-29
    • 1970-01-01
    • 2019-12-26
    • 2020-08-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多