我正在尝试带一组二十人(标记为1 - 20
)并将他们分成5个小组,每个小组4个,根据这些人希望与谁表达的偏好。
20人组中的每个人都可以表达0,1,2,3或4个偏好。例如,person1
可以选择0(不喜欢他们与谁在一起),或14(在person14
组中)或者可以表示与人14,20,6组成一组, 7.理想情况下,每个有偏好的人都会在一个至少有一个选择的群体中。
关于算法的想法?
答案 0 :(得分:2)
您遇到的问题与C#无关,该算法与语言无关。
此问题的典型实现是backtracking。
更多信息:
另一种方法(我会这样做):Genetic Algorithms。
答案 1 :(得分:0)
这可能在SO上要求太多,但认为这个问题非常有趣,所以这里有一些想法。
正如 Victor Hurdugaci 所说,这主要是一个独立于语言的算法问题(虽然我很乐意看到下面的例子用LINQ实现!)
您的问题中描述的问题无法产生完美的结果,即它是一个优化问题(因此您无法使用约束满足算法来解决它)。您必须找到一种算法,该算法根据一些表明结果有多好的函数(称为适应度函数),从所有可能结果的集合中找到最佳结果。
Naive Brute force Solution(伪代码)
我们从一组人开始(这里:4简化事情):
people = { a, b, c, d }
我们可以使用choose
运算符找到所有可能的固定大小的子组(此处为:2):
groups = people.choose(2) // = { {a,b} {a,c} {a,d} {b,c} {b,d} {c,d} }
我们可以再次使用choose
运算符找到所有可能的子组组合:
combi = groups.choose(4/2) // = { {ab,ac} {ab,ad} {ab,bc} {ab,bd}
// {ab,cd} {ac,ad} {ac,bc} {ac,bd}
// {ac,cd} {ad,bc} {ad,bd} {ad,cd}
// {bc,bd} {bc,cd} {bd,cd} }
显然,人们不能同时分成两组,所以我们删除所有无效组合:
combi2 = combi.select(g => g.bigUnion().size == 4)
// = { {ab,cd}, {ac,bd}, {ad,bc} }
现在你必须根据一些健身功能找到“最佳”项目,即根据偏好得分最佳的组合。
result = combi2.maximumBy(g => fitness(g))
例如,如果a
优先选择b
,b
,c
和d
没有任何偏好,那么{{1应该为calculateScore
返回的分数高于{ab,cd}
和{ac,bd}
的分数。
改进的解决方案
有几种算法可以解决这种优化问题。我认为Hill climbing算法很适合。