C#如何生成符合指定条件、无重复成员的组合分组方案
人员分组最优组合优化方案
核心问题根因
你当前方案的性能问题来源于全量枚举所有可能的组合,没有提前剪枝无效路径,当人数超过10之后组合数会指数级上升。下面是3种不同适用场景的优化方案:
方案1:贪心回溯剪枝(普通场景首选,平衡效果与性能)
你可以保留之前生成合法单组(大小为PreferredGroupSize或PreferredGroupSize±1)并按score降序排序的逻辑,后续用回溯选组,全程加剪枝规则避免无效遍历:
- 选组时严格控制两类组的数量:先选够
numNormalSizeGroups个标准大小组,再选numOddSizeGroups个调整大小组,避免混选产生的无效路径 - 每次选组时校验:当前组与已选组无重叠成员
- 加入两类剪枝规则,触发时直接终止当前分支的遍历:
- 剩余未分配人数 < 剩余待选组的最小总人数(比如还需选2个组,最小总大小为4+4=8,剩余人数仅7时直接剪枝)
- 当前已选组的总score + 剩余待选k个组的理论最高score(直接取未使用的前k个最高单组score加总,不用校验重叠) < 已经找到的最优解总score,当前分支不可能产生更优解,直接剪枝
- 找到符合要求的有效分组就存入结果集,攒够M个后直接终止整个流程,不需要遍历所有可能性
方案2:状态压缩动态规划(人数≤30时,可得到全局最优解)
总人数N不超过30时,用二进制掩码表示人员选中状态,完全可以覆盖你的19人场景:
- 定义
dp[mask]为选中mask对应人员时可获得的最高总score,同时存储对应的分组明细 - 初始状态:
dp[0] = 0(无人员选中时score为0) - 状态转移:遍历所有合法掩码,对每个掩码,找所有与当前掩码无重叠的合法单组,计算新掩码的score,若高于
dp[新掩码]的原有值则更新 - 最终
dp[全1掩码]对应的分组就是全局最优解
19人场景下掩码总数仅为2^19=524288,算力开销极低,完全不会出现组合爆炸问题
方案3:启发式搜索(人数>30时,快速获取近似最优解)
如果人员数量较多,不需要100%最优解,仅需要高分的前M个分组,可以用启发式算法:
- 遗传算法:随机生成M个合法分组作为初始种群,迭代过程中交叉、变异组内成员,每轮保留总score最高的前K个分组,迭代数十轮即可得到接近最优的结果
- 模拟退火算法:随机生成初始合法分组,每次随机交换两个组的成员,总score升高则直接保留,降低则按概率保留,避免陷入局部最优
额外优化建议
- 提前缓存所有单组的score,避免重复计算同一个组合的兼容性分数
- 你当前用的
Dictionary<List<Person>, float>存储结构存在问题:List作为默认引用类型,会用引用地址做相等校验,建议自定义组的哈希规则,或者用人员ID排序后的字符串作为Key,避免存储重复分组 - 如果不需要全局最优解,可直接按score从高到低选无重叠的合法单组,凑够组数就直接返回,性能可提升数个量级
内容的提问来源于stack exchange,提问作者Max.D.Kaos
相关产品推荐
相关产品推荐

