如何优化联赛对阵场地分配算法,实现均匀且可扩展的分配?
联赛场地均匀分配优化方案
原始赛程信息
以下是8支球队、16周的联赛赛程(每周4场对阵):
1,2 @ 1,7 @ 4,5 @ 6,3 @ 8 2,4 @ 2,1 @ 3,8 @ 5,6 @ 7 3,4 @ 1,5 @ 3,2 @ 6,7 @ 8 4,8 @ 2,6 @ 4,1 @ 5,3 @ 7 5,6 @ 1,2 @ 3,7 @ 5,4 @ 8 6,5 @ 2,3 @ 4,8 @ 6,1 @ 7 7,8 @ 1,6 @ 3,4 @ 5,2 @ 7 8,1 @ 2,8 @ 3,6 @ 5,4 @ 7 9,3 @ 1,2 @ 4,7 @ 6,5 @ 8 10,6 @ 2,1 @ 4,3 @ 5,8 @ 7 11,5 @ 1,7 @ 3,4 @ 6,2 @ 8 12,3 @ 2,8 @ 4,1 @ 6,5 @ 7 13,7 @ 1,4 @ 3,2 @ 5,6 @ 8 14,7 @ 2,5 @ 4,3 @ 6,1 @ 8 15,2 @ 1,7 @ 4,5 @ 6,3 @ 8 16,4 @ 2,1 @ 3,8 @ 5,6 @ 7
当前问题与需求
需要将每周对阵均匀分配至X个场地(X等于每周对阵数,此处为4个)。现有算法通过跟踪球队场地出场次数计算权重,选择权重最低的场地分配,但存在以下问题:
- 分配不均匀,例如球队1在场地1可能出场5次,而理想值应为4次
- 缺乏可扩展性,无法适配不同规模联赛(如12支球队每周6场对阵,需实现3、3、3、3、2、2这类均匀分布的分配结果)
原始算法代码
schedule.GetAllScheduledRecords().ForEach(sr => { var availableLocations = new List<int>(locationKeys); sr.GetAllLeagueMatches().ForEach(lm => { var weights = new List<Tuple<int, int>>(); availableLocations.ForEach(location => weights.Add(new Tuple<int, int>(locationWeight[lm.GetAwayTeam()][location] + locationWeight[lm.GetHomeTeam()][location], location))); var lowestWeight = weights.Min(x => x.Item1); var lowestLocations = weights.Where(x => x.Item1 == lowestWeight).ToList(); var locationIndex = rng.Next(lowestLocations.Count); var chosenLocation = lowestLocations[tableIndex].Item2; // 存在变量名错误,应为locationIndex availableLocations.Remove(chosenLocation); locationAssignments[chosenLocation][sr.GetLeagueWeek() - 1] = lm; locationWeight[lm.GetAwayTeam()][chosenLocation]++; locationWeight[lm.GetHomeTeam()][chosenLocation]++; }); });
优化方案
1. 预计算理想出场基准
先为每支球队在每个场地计算理想出场次数:
- 总出场次数:单队总对阵数 = 赛季周数 × 单队每周出场次数(如8队16周,单队总出场16次)
- 理想单场地次数:总出场次数 ÷ 场地数,若无法整除,则分为「商」和「商+1」两个档位,记录需要分配「商+1」次数的场地数量(如12队总出场18次、6个场地,3个场地分配3次,3个场地分配2次)
分配时,将「当前次数与理想次数的差值」纳入权重计算,避免过早偏离理想值。
2. 优化权重计算逻辑
原权重仅计算两队当前出场次数之和,改为用平方差放大偏离惩罚:
权重 = (客队当前场地次数 - 客队理想场地次数)² + (主队当前场地次数 - 主队理想场地次数)²
优先选择能让两队更接近理想次数的场地,若多个场地权重相同,再随机选择。
3. 每周分配后全局校验
每周分配完成后,检查各场地的分配情况:
- 若某场地的总分配次数(或某队在该场地的次数)偏离理想值过多,回溯调整该周的分配顺序(如更换先分配的对阵)
- 大规模联赛可采用「贪心+局部微调」模式,每周分配后做小范围调整,保证整体均匀性
4. 适配多场景扩展性
- 新增配置参数:总球队数、赛季周数、场地数,自动计算每队在各场地的理想出场次数区间(如
minCount = 总出场数 / 场地数,maxCount = minCount + 1,记录需要maxCount的场地数量) - 权重逻辑动态调整,无需硬编码,适配不同规模联赛
5. 修复原代码bug
原代码中chosenLocation = lowestLocations[tableIndex].Item2存在变量名错误,修正为:
var locationIndex = rng.Next(lowestLocations.Count); var chosenLocation = lowestLocations[locationIndex].Item2;
内容的提问来源于stack exchange,提问作者Shar1er80
相关产品推荐
相关产品推荐

