【问题标题】:Sorting People into Groups based on Votes根据投票将人员分组
【发布时间】:2014-02-14 12:49:54
【问题描述】:

我在寻找用于对人员数据集进行排序的算法时遇到问题。我尽量详细解释:

故事从一项调查开始。一群人,假设 600 人可以在 20-25 个项目之间进行选择。他们提出了#1-wish、#2-wish 和#3-wish,其中#1 是他们想要参与的最想要的项目,并希望 3 是“不完美但最能接受的选择”。

这些项目的参与者人数有限。每个项目可以加入大约 30 人(根据人数和项目数)。

该算法将人员置于不同的项目中,并应找到最佳组合。

问题是你不能把所有的人的第 1 个愿望 X 放在某个项目中,而把所有其他人的第 1 个愿望 X 放在第 2 个愿望中,因为那不是最多的”对每个人来说都是最幸福的”。

当你想象每个获得第一名的人都希望你得到 100 分,获得第二名的每个人都希望得到 60 分,第三名的人都希望得到 30 分,而没有获得第一名的人时,你可能会想到我的意思他的愿望0分。并且您希望获得尽可能多的积分。

我希望你能解决我的问题。这是一个学校项目日。 有什么可以帮助我的吗?你有什么主意吗?我会感谢每一个小费!

亲切的问候

【问题讨论】:

    标签: algorithm sorting design-patterns


    【解决方案1】:

    我的算法是这样的:

    mainloop
     wishlevel = 1
      loop
       Distribute people into all projects according to wishlevel wish
       loop through projects, counting population
        If population exceeds maximum
         Distribute excess non-redistributed people into their wishlevel+1 projects that are under-populated
         tag distributed people as 'redistributed' to avoid moving again
        endif
       endloop
      wishlevel = wishlevel + 1
     loop until wishlevel == 3    
    mainloop until no project exceeds max population
    

    这应该会在数据集上进行多次传递,直到一切顺利。如果您限制重新分配已重新分配的人员,则此算法可能会导致无限循环,以防随着算法的进展一个项目被此类人员填满,因此您可以在没有该限制的情况下尝试它。

    【讨论】:

      【解决方案2】:

      您可以通过将其表述为最小成本网络流问题来优化解决此问题。

      为每个人添加一个节点,为每个项目添加一个。

      根据个人和项目的偏好设置流程成本。

      (由于 Networkx 提供了最小成本流,但不是最大成本流,我将成本设置为 负数。)

      例如,使用 Networkx 和 Python:

      import networkx as nx
      
      G=nx.DiGraph()
      
      prefs={'Tom':['Project1','Project2','Project3'],
             'Dick':['Project2','Project1','Project3'],
             'Harry':['Project1','Project3','Project1']}
      
      capacities={'Project1':2,'Project2':10,'Project3':4}
      
      num_persons=len(prefs)
      G.add_node('dest',demand=num_persons)
      A=[]
      for person,projectlist in prefs.items():
          G.add_node(person,demand=-1)
          for i,project in enumerate(projectlist):
              if i==0:
                  cost=-100 # happy to assign first choices
              elif i==1:
                  cost=-60 # slightly unhappy to assign second choices
              else:
                  cost=-30 # very unhappy to assign third choices
              G.add_edge(person,project,capacity=1,weight=cost) # Edge taken if person does this project
      
      for project,c in capacities.items():
              G.add_edge(project,'dest',capacity=c,weight=0)
      
      flowdict = nx.min_cost_flow(G)
      for person in prefs:
          for project,flow in flowdict[person].items():
              if flow:
                  print person,'joins',project
      

      在这段代码中,Tom 的第一选择是 Project1,然后是 Project2,然后是 Project3。

      容量字典指定了每个项目可以加入的人数上限。

      【讨论】:

      • 哇!太棒了!我对Python或networkx一无所知,但我希望我能处理好这个,应该不难。还有一个问题。我还可以为项目设置最少人数吗?
      • 当然,你只是设置了一个项目的需求,例如对于 Project1 至少有 10 个添加 G.add_node('Project1',demand=10) 并将 dest 的需求减少 10 以匹配。
      猜你喜欢
      • 2013-11-15
      • 1970-01-01
      • 2023-04-10
      • 2020-08-11
      • 1970-01-01
      • 2016-08-08
      • 2020-08-17
      • 2023-03-02
      相关资源
      最近更新 更多