匹配队友偏好的算法
Posted
技术标签:
【中文标题】匹配队友偏好的算法【英文标题】:Algorithm to match teammate preferences 【发布时间】:2022-01-10 07:11:54 【问题描述】:我有一种情况,我必须创建一个 C# 例程,该例程具有以下逻辑来获取人员列表并根据偏好将他们分成 2 个团队:
我有一个包含 20 个名称的数组:
var names = new List()"Joe", "Bill", "Scott", "Jonathan", . . .
每个名字可以给出 0 到 3 个偏好,所以对于每个名字,我有一个长度为 0 到 3 的数组,并且是一个字符串数组,列表中有其他名字(他们是他们想加入团队的人)
我现在需要解决取 20 个人的列表并将他们分成 2 个团队,并根据人们的偏好进行优化来创建团队(子列表)。因此,每个人都应该在他们的团队中选择至少一个他们喜欢的人(如果在数学上可能的话)。没有一个人高于其他人的优先级,只是试图针对最高匹配数进行优化。
我可以将字符串列表转换为对象列表
List<Person> list = CreateList(array)
其中 Person 类如下
public class Person
public string Name;
public List<Person> Preferences;
但现在我想弄清楚如何使用这个数据结构来生成 2 个团队,我最终得到 2 个团队列表,每组 10 人。
【问题讨论】:
我觉得有很多细节被掩盖了。你如何确定谁是第一优先,谁被推到下一个?输出列表是否必须完全相等?这感觉类似于排名投票算法。我觉得在编写代码之前弄清楚这在没有 c# 的情况下如何在纸上工作很重要。 FWIW 这对我来说就像一个Bipartite graph 问题。 只有 184756 种可能的方法可以将 20 人分成 10 人一组。您可以轻松尝试所有方法,看看哪种方法最好。 @gunr2171 - 我更新了问题以添加更多关于优先级的详细信息 【参考方案1】:最佳流量方法可以解决您的问题 - 最大化图表中的流量,该图表分支容量表达偏好。有一个N^3算法。
这里有一个例子:Algorithm for optimal matching with choices and ranking
【讨论】:
【参考方案2】:与其设置邻接矩阵并尝试通过线性代数提取一些有意义的向量解,我认为您可能会从迭代的“队长”类型模型中获得一些好处。
我首先将每个人的偏好表示为一个行向量,模仿邻接矩阵的行。
为了便于说明,我以 4 个人为例:A、B、C 和 D。A 和 D 想在一起,B 想和 C 在一起,C 想和 A 在一起。
邻接矩阵的行是[1,0,0,1],[0,1,1,0],[1,0,1,0],[1,0,0,1]。所以我会继续将每个人表示为邻接矩阵中的行。 A 是 [1,0,0,1],B 是 [0,1,1,0],C 是 [1,0,1,0],D 是 [1,0,0,1]。
现在我将创建团队队长。我将寻找两个点积最小的向量。您的要求不保证存在零点产品。例如,每个人都可能想和一个特定的人在一起。但是你仍然可以找到两个点积最小的向量,并且在实践中可能是完全正交的。
现在让这两个人成为队长。在本例中,这意味着 A=[1,0,0,1] 和 B=[0,1,1,0] 是可行的队长。
现在迭代地允许他们开始挑选他们的团队。 A 可以通过与 C 和 D 的点积来找到他的最佳新成员,并且观察 D 产生最大的点积,从而产生团队 A,D, B,C。
当然,就您而言,它并不止于此。因此,让我们考虑一下如果还有一个 E、F、G 和 H 等待被选中会发生什么。在这种情况下,团队 A,D 会将(列)矩阵 [A][D] 与(列)向量 [E]、[F]、[G] 和 [H] 相乘,然后查看哪个产品具有最大范数,选择它并允许团队 B,C 通过相同的过程选择其最新成员:maxnorm([B][C]*[candidate])。
【讨论】:
以上是关于匹配队友偏好的算法的主要内容,如果未能解决你的问题,请参考以下文章