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

基于饮食偏好的3组人群分配算法实现问题,适配任意参与人数

人员分组算法实现方案

前置规则梳理

  • 人员饮食类型共4类:meat(仅可去A组)、vegan(仅可去B组)、vegetarian(优先去C组,C放不下再去B组)、no_food_preference(可去任意组,用于补全各组6人倍数的缺口)
  • 各组准入要求:
    • Group A:仅允许meat、no_food_preference进入
    • Group B:仅允许vegan、vegetarian、no_food_preference进入
    • Group C:仅允许vegetarian、no_food_preference进入
  • 最终要求:每个组总人数必须是6的整数倍

算法执行步骤

  1. 人员池拆分:将所有人员按饮食偏好拆分为4个独立池,分别统计各池人数
  2. 强制归属分配:将只能进入单个组的meat全部划入A组,vegan全部划入B组
  3. 预留A组补员:A组仅能通过无偏好人员补全到6的倍数,先从无偏好池中扣除A组所需的最少补员数量,完成A组第一次人数凑整
  4. 分配vegetarian群体:优先将vegetarian划入C组,匹配无偏好池剩余人数将C组总人数凑整到6的倍数,无法放入C组的vegetarian全部划入B组
  5. B组人数凑整:用剩余无偏好人员将B组总人数凑整到6的倍数
  6. 剩余无偏好人员处理:此时剩余无偏好人员数量一定是6的整数倍,可按6人一组批量加入任意符合准入规则的组即可

代码实现(针对示例数据)

import pandas as pd

# 加载示例数据
df = pd.DataFrame(
 {
 "user_id": [i for i in range(1, 55)],    
 "Master_FoodPreference": ["meat", "vegetarian", "meat", "vegan", "meat", "vegetarian", "meat", "vegetarian", "no_food_preference", 
                           "meat",'no_food_preference', 'vegetarian',"meat", "meat",
                           "vegetarian", "vegetarian", "vegan", "vegetarian", "vegetarian", "no_food_preference", "vegan", 
                           "vegetarian", "vegetarian", "vegetarian", "vegetarian", "vegetarian", "vegetarian",
                           "meat", "vegetarian", "meat", "vegetarian", "no_food_preference", "vegetarian", "vegetarian", "vegetarian", 
                           "vegetarian", "vegetarian", "vegetarian", "vegetarian", "vegetarian", "no_food_preference", 
                           "no_food_preference", "no_food_preference", "meat", "no_food_preference", "meat", "meat", 
                           "vegan", "no_food_preference", "no_food_preference", "vegan" ,"no_food_preference" ,"vegan" ,"vegan" ]
 }
)

# 步骤1:拆分四个人员池
pool_meat = df[df['Master_FoodPreference'] == 'meat']['user_id'].tolist()
pool_vegan = df[df['Master_FoodPreference'] == 'vegan']['user_id'].tolist()
pool_vegetarian = df[df['Master_FoodPreference'] == 'vegetarian']['user_id'].tolist()
pool_no_pref = df[df['Master_FoodPreference'] == 'no_food_preference']['user_id'].tolist()

# 初始化各组
group_a = []
group_b = []
group_c = []

# 步骤2:强制分配只能去单组的人员
group_a.extend(pool_meat)
group_b.extend(pool_vegan)

# 步骤3:补全A组到6的倍数
need_a = (6 - len(group_a) % 6) % 6
group_a.extend(pool_no_pref[:need_a])
pool_no_pref = pool_no_pref[need_a:]

# 步骤4:优先分配vegetarian到C组并凑整
vt_count = len(pool_vegetarian)
need_c = (6 - vt_count % 6) % 6
if need_c <= len(pool_no_pref):
    # 全部vegetarian都可放入C组
    group_c.extend(pool_vegetarian)
    group_c.extend(pool_no_pref[:need_c])
    pool_no_pref = pool_no_pref[need_c:]
    remaining_vt = []
else:
    # 容量不足,调整C组可容纳的vegetarian数量
    available_total = vt_count + len(pool_no_pref)
    max_vt_in_c = vt_count - (available_total % 6)
    group_c.extend(pool_vegetarian[:max_vt_in_c])
    group_c.extend(pool_no_pref)
    pool_no_pref = []
    remaining_vt = pool_vegetarian[max_vt_in_c:]

# 剩余vegetarian放入B组
group_b.extend(remaining_vt)

# 步骤5:补全B组到6的倍数
need_b = (6 - len(group_b) %6) %6
group_b.extend(pool_no_pref[:need_b])
pool_no_pref = pool_no_pref[need_b:]

# 步骤6:剩余无偏好人员(一定是6的倍数)批量加入A组(也可加入B/C,均符合规则)
group_a.extend(pool_no_pref)

# 结果验证与输出
print(f"Group A总人数:{len(group_a)},是否为6的倍数:{len(group_a)%6==0}")
print(f"Group B总人数:{len(group_b)},是否为6的倍数:{len(group_b)%6==0}")
print(f"Group C总人数:{len(group_c)},是否为6的倍数:{len(group_c)%6==0}")

示例运行结果

针对给出的54人示例数据运行代码后,输出如下:

  • Group A总人数18,人员为全部meat类人员+6名无偏好人员,符合准入规则
  • Group B总人数12,人员为全部vegan类人员+5名无偏好人员,符合准入规则
  • Group C总人数24,人员为全部vegetarian类人员,符合准入规则
    所有组人数均为6的整数倍,完全满足需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 13:57:03