速度约会算法

时间:2009-06-09 07:35:44

标签: algorithm language-agnostic permutation combinations

我在咨询机构工作,大部分时间都在客户所在地。因此,我很少见到我的同事。为了更好地了解彼此,我们将安排一个晚宴。将有许多小桌子,所以人们可以聊天。为了在聚会期间尽可能多地与不同的人交谈,每个人都必须按照一定的时间间隔来换桌子,比如每小时一次。

如何编写创建表切换计划的程序?只是给你一些数字;在这种情况下,将有大约40人,每张桌子最多可以有8个人。但是,算法必须是通用的

10 个答案:

答案 0 :(得分:11)

这是一个想法 从第一个人的角度来看第一个工作..让他叫他X
X必须与会议室中的所有其他人见面,所以我们应该将剩下​​的人分成n组(其中n =#___people / capacity_per_table)并让他每次迭代与其中一组人员坐在一起 现在X已被照顾,我们将考虑下一个人Y
WLOG Y是X必须在第一次迭代中坐下来的人..所以我们已经知道Y的表组在那个时间范围内......然后我们应该将剩余的人分成小组,这样每个小组每次连续坐着Y.迭代..并且对于每次迭代,X的组和Y的组没有共同的人 ..我想,如果你继续做这样的事情,你将得到一个最佳的解决方案(如果存在的话)

或者你可以通过给每个人一张卡片来解决问题,他们可以写下他们用餐的所有人的名字......并且在活动结束时,向人们提供一些奖品。他们卡片中的大多数名字

答案 1 :(得分:6)

为什么不模仿现实世界?

class Person { 
    void doPeriodically() {
         do {
             newTable = random (numberOfTables);
         } while (tableBusy(newTable))
         switchTable (newTable) 
    }
}

哦,请注意,有一个类似的算法可以找到一个交配伙伴,并且传言这对99%没有花费所有空闲时间回答编程问题的人都有效...

答案 2 :(得分:5)

这听起来像是遗传算法的应用:

  1. 选择40位客人的随机排列 - 这是一个座位安排
  2. 重复随机排列N次(n是你在夜间换座位的次数)
  3. 将排列组合在一起 - 这是一个生物的染色体
  4. 重复你想要在一代中培育多少生物
  5. 健康分数是每个人在一个晚上看到的人数(或者 - 他们没有看到的人数的倒数)
  6. 使用常规方法培育,变异和引入新生物,并重复直至得到满意的答案
  7. 您可以在健身中添加您喜欢的任何其他因素,例如男/女比例等,而不会大幅改变基本方法。

答案 3 :(得分:4)

答案 4 :(得分:3)

您可能需要查看combinatorial design theory

答案 5 :(得分:2)

直觉上我认为你不能比perfect shuffle做得更好,但这超出了我对咖啡前的认知来证明它。

答案 6 :(得分:2)

这个非常好笑! :d

我尝试了不同的方法,但adi92(card + prize)建议的逻辑是比我尝试过的任何其他方法更好的逻辑。

它的工作原理如下:

  1. 一个人来到并检查所有表格
  2. 对于每张有免费座位的桌子,他会计算他还有多少人见面,然后选择一个人不知名的人
  3. 如果两张桌子的人数相同,那么这个家伙会选择一个拥有更多免费座位的人,这样就有更多可能会遇到更多新人
  4. 在每个回合中,坐席的人的顺序是随机的(这可以避免可能的无限循环),这是python中工作算法的“演示”:

    import random
    
    class Person(object):
    
        def __init__(self, name):
            self.name = name
            self.known_people = dict()
    
        def meets(self, a_guy, propagation = True):
            "self meets a_guy, and a_guy meets self"
            if a_guy not in self.known_people:
                self.known_people[a_guy] = 1
            else:
                self.known_people[a_guy] += 1
    
            if propagation: a_guy.meets(self, False)
    
        def points(self, table):
            "Calculates how many new guys self will meet at table"
            return len([p for p in table if p not in self.known_people])
    
        def chooses(self, tables, n_seats):
            "Calculate what is the best table to sit at, and return it"
            points = 0
            free_seats = 0
            ret = random.choice([t for t in tables if len(t)<n_seats])
    
            for table in tables:
                tmp_p = self.points(table)
                tmp_s = n_seats - len(table)
                if tmp_s == 0: continue
                if tmp_p > points or (tmp_p == points and tmp_s > free_seats):
                    ret = table
                    points = tmp_p
                    free_seats = tmp_s
    
            return ret
    
        def __str__(self):
            return self.name
        def __repr__(self):
            return self.name
    
    
    def Switcher(n_seats, people):
        """calculate how many tables and what switches you need
            assuming each table has n_seats seats"""
    
        n_people = len(people)
        n_tables = n_people/n_seats
    
        switches = []
        while not all(len(g.known_people) == n_people-1 for g in people):
            tables = [[] for t in xrange(n_tables)]
    
            random.shuffle(people) # need to change "starter"
    
            for the_guy in people:
                table = the_guy.chooses(tables, n_seats)
                tables.remove(table)
                for guy in table:
                    the_guy.meets(guy)
                table += [the_guy]
                tables += [table]
    
            switches += [tables]
    
        return switches
    
    
    
    lst_people = [Person('Hallis'),
          Person('adi92'),
          Person('ilya n.'),
          Person('m_oLogin'),
          Person('Andrea'),
          Person('1800 INFORMATION'),
          Person('starblue'),
          Person('regularfry')]    
    
    
    
    s = Switcher(4, lst_people)
    
    print "You need %d tables and %d turns" % (len(s[0]), len(s))
    turn = 1
    for tables in s:
        print 'Turn #%d' % turn
        turn += 1
        tbl = 1
        for table in tables:
            print '  Table #%d - '%tbl, table
            tbl += 1
        print '\n'
    

    这将输出如下内容:

    You need 2 tables and 3 turns
    Turn #1
      Table #1 -  [1800 INFORMATION, Hallis, m_oLogin, Andrea]
      Table #2 -  [adi92, starblue, ilya n., regularfry]
    
    
    Turn #2
      Table #1 -  [regularfry, starblue, Hallis, m_oLogin]
      Table #2 -  [adi92, 1800 INFORMATION, Andrea, ilya n.]
    
    
    Turn #3
      Table #1 -  [m_oLogin, Hallis, adi92, ilya n.]
      Table #2 -  [Andrea, regularfry, starblue, 1800 INFORMATION]
    

    由于随机性,它并不总是带有最小数量的开关,特别是对于较大的人群。然后你应该运行它几次并以较少的转弯得到结果(所以你不要强调聚会上的所有人:P),并且编码很容易:P

    PS: 是的,你可以节省奖金:P

答案 7 :(得分:1)

您还可以查看稳定的匹配问题。该问题的解决方案涉及使用max-flow算法。 http://en.wikipedia.org/wiki/Stable_marriage_problem

答案 8 :(得分:0)

我不打扰遗传算法。相反,我会做以下事情,这是对重复完美洗牌的一点点改进。

虽然(有两个人没有见过面):

  1. 考虑图表,其中每个节点都是客人,如果A和B没有坐在同一个表中,则边缘(A,B)存在。找到此图表的所有connected components。如果有任何连接的组件大小&lt; tablesize,在表格上安排那些连接的组件。请注意,即使这实际上是一个称为Bin打包的硬问题的实例,但首先适合减少可能会很好,这可以通过按从大到小的顺序对连接的组件进行排序,然后将它们中的每一个放入转到他们适合的第一张桌子。
  2. 对剩余元素执行随机排列。 (换句话说,随机安排剩下的人,最初将是每个人。)
  3. 指示轮数的增量计数器。
  4. 重复上述步骤一段时间,直到轮数似乎收敛。

答案 9 :(得分:0)

WRT @ Neodymium的评论,这是相关网站上的page

它讨论了遗传算法。