基于可用时间的Automated Scheduling一对一师生周排期工具实现咨询
问题本质定义
这是典型的二分图最大匹配问题,属于运筹学资源分配方向的经典场景,你之前尝试的贪心逻辑失效的核心原因是缺少回溯机制:提前占用的时段可能导致后续可用时间更少的学生完全无时段可选,没有回退调整能力自然无法生成合规排期。
该场景的二分图模型可以直接套用:
- 左节点:所有需要会面的学生
- 右节点:教职工一周内所有可用于会面的小时粒度时段
- 边的存在条件:对应学生在对应时段标记为可用
你需要的合规排期本质就是求该二分图的完美匹配:每个学生节点恰好匹配一个唯一的时段节点,没有重复匹配,匹配数等于学生总数。
落地实现步骤
第一步:数据标准化
先将原始数据整理为统一结构,以Python为例:
- 学生可用时间用
dict存储,key为学生ID,value为可用时段的集合,时段可通过(周几, 小时)的元组表示,比如(2, 10)代表周二上午10点 - 前置校验:如果总可用时段数小于学生总数,直接返回无解,无需运行后续算法
第二步:匹配算法实现
中小规模场景(学生数<1000,总时段数<200)直接使用Hopcroft-Karp算法即可,性能比普通DFS增广路径高1个数量级,完全满足需求,核心逻辑参考伪代码:
def generate_schedule(student_available: dict, all_slots: set) -> dict|None: # 初始化时段匹配映射:key为时段,value为匹配到的学生,初始为空 slot_match = {slot: None for slot in all_slots} result = {} def dfs(student_id, available_slots, visited): for slot in available_slots: if slot not in visited: visited.add(slot) # 时段未被占用,或占用该时段的学生可以找到其他替代时段 if slot_match[slot] is None or dfs(slot_match[slot], student_available[slot_match[slot]], visited): slot_match[slot] = student_id return True return False for stu_id in student_available: visited_slots = set() if not dfs(stu_id, student_available[stu_id], visited_slots): # 存在学生找不到可匹配时段,无完美匹配解 return None # 转换为学生到时段的映射结果 for slot, stu_id in slot_match.items(): if stu_id is not None: result[stu_id] = slot return result
第三步:结果校验
拿到匹配结果后做两层规则校验,避免异常:
- 所有学生都有对应的匹配时段,无遗漏
- 所有匹配时段无重复,满足会面时间不重叠要求
扩展优化
如果后续需要新增约束(比如教职工单日会面不超过6次、学生会面尽量安排在工作日白天等),可以将问题升级为加权二分图匹配,给不同时段设置对应权重,用KM算法求最大权完美匹配即可,核心框架不需要调整。
内容的提问来源于stack exchange,提问作者Michael Eerdekens
相关产品推荐
相关产品推荐

