You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ORTools/Python:求解最优球队时如何追踪同俱乐部/国家球员选中数量?

解决方案

核心思路

要解决这个问题,关键是把「同俱乐部/国家/联赛且处于最佳位置的选中球员数量」转化为OR-Tools能识别的变量和约束,再将数量映射到0-3的参数值,最终代入目标函数。

步骤1:定义分组计数变量

针对俱乐部、国家、联赛三个维度,分别创建整数变量来记录对应分组中「处于最佳位置且被选中」的球员数量:

# 假设roster是所有球员卡列表,每个card有club、country、league、best_position属性
club_counts = {}
country_counts = {}
league_counts = {}

# 初始化俱乐部计数变量
for card in roster:
    club = card.club
    if club not in club_counts:
        # 最多11人,所以范围0-11
        club_counts[club] = model.NewIntVar(0, 11, f"club_count_{club}")

# 国家和联赛的计数变量同理
for card in roster:
    country = card.country
    if country not in country_counts:
        country_counts[country] = model.NewIntVar(0, 11, f"country_count_{country}")

for card in roster:
    league = card.league
    if league not in league_counts:
        league_counts[league] = model.NewIntVar(0, 11, f"league_count_{league}")

步骤2:建立计数变量与选中状态的约束

让计数变量等于对应分组中「处于最佳位置且被选中」的球员数量之和(card_vars是布尔变量,求和即计数):

# 俱乐部计数约束
for club in club_counts:
    model.Add(club_counts[club] == sum(
        card_vars[(card, card.best_position)]
        for card in roster
        if card.club == club
    ))

# 国家计数约束
for country in country_counts:
    model.Add(country_counts[country] == sum(
        card_vars[(card, card.best_position)]
        for card in roster
        if card.country == country
    ))

# 联赛计数约束
for league in league_counts:
    model.Add(league_counts[league] == sum(
        card_vars[(card, card.best_position)]
        for card in roster
        if card.league == league
    ))

步骤3:将计数映射为0-3的参数值

创建bonus变量,通过约束将计数范围映射到0-3的参数(按游戏规则:0人→0,1人→1,2人→2,≥3人→3):

# 俱乐部bonus变量
club_bonus = {}
for club in club_counts:
    club_bonus[club] = model.NewIntVar(0, 3, f"club_bonus_{club}")
    # 添加映射约束
    model.Add(club_bonus[club] == 0).OnlyEnforceIf(club_counts[club] == 0)
    model.Add(club_bonus[club] == 1).OnlyEnforceIf(club_counts[club] == 1)
    model.Add(club_bonus[club] == 2).OnlyEnforceIf(club_counts[club] == 2)
    model.Add(club_bonus[club] == 3).OnlyEnforceIf(club_counts[club] >= 3)

# 国家和联赛的bonus变量同理
country_bonus = {}
for country in country_counts:
    country_bonus[country] = model.NewIntVar(0, 3, f"country_bonus_{country}")
    model.Add(country_bonus[country] == 0).OnlyEnforceIf(country_counts[country] == 0)
    model.Add(country_bonus[country] == 1).OnlyEnforceIf(country_counts[country] == 1)
    model.Add(country_bonus[country] == 2).OnlyEnforceIf(country_counts[country] == 2)
    model.Add(country_bonus[country] == 3).OnlyEnforceIf(country_counts[country] >= 3)

league_bonus = {}
for league in league_counts:
    league_bonus[league] = model.NewIntVar(0, 3, f"league_bonus_{league}")
    model.Add(league_bonus[league] == 0).OnlyEnforceIf(league_counts[league] == 0)
    model.Add(league_bonus[league] == 1).OnlyEnforceIf(league_counts[league] == 1)
    model.Add(league_bonus[league] == 2).OnlyEnforceIf(league_counts[league] == 2)
    model.Add(league_bonus[league] == 3).OnlyEnforceIf(league_counts[league] >= 3)

步骤4:调整目标函数

将calculate_rating的第三个参数替换为对应的bonus值(这里假设游戏取俱乐部加成,若需要叠加多个维度,可在calculate_rating中处理):

model.Maximize(sum([
    card.calculate_rating(position, coefficients, club_bonus[card.club]) * card_vars[(card, position)]
    for card in roster
    for position in max_player_positions
]))

额外约束补充

确保球员不会被重复选中,且总人数为11:

# 每个球员最多被选中一次
for card in roster:
    model.Add(sum(card_vars[(card, pos)] for pos in max_player_positions) <= 1)

# 总选中人数为11
model.Add(sum(card_vars.values()) == 11)

内容的提问来源于stack exchange,提问作者Bastien_F

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 17:37:01