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

Python实现7员工7周多约束排班并输出至CSV

7周员工排班问题的Python实现方案

需求回顾

  • 7名员工,7周(49天),每天3个班次:早班(M)、中班(A)、晚班(N)
  • 约束1:每天的三个班次必须由不同员工负责
  • 约束2:每个员工在49天内,每个工作日的每个班次仅排1次(如员工1仅排1次周一早班、1次周一中班等)
  • 约束3:员工值晚班后,后续2天不得排班

实现思路

采用贪心算法逐天排班,优先处理晚班(因晚班有禁排约束),确保每一步选择都满足所有约束:

  1. 跟踪每个员工已排过的(工作日, 班次)组合,确保不违反约束2
  2. 跟踪每个员工的禁排日期,确保晚班后两天不排班(约束3)
  3. 每天的班次选择不同员工,满足约束1

完整代码

import csv
import random

# 配置参数
EMPLOYEES = [f"员工{i+1}" for i in range(7)]
SHIFTS = ["M", "A", "N"]
DAYS_PER_WEEK = 7
TOTAL_DAYS = 7 * DAYS_PER_WEEK
WEEKDAY_NAMES = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"]

def generate_schedule():
    # 记录每个员工已排的(工作日, 班次)组合
    emp_shift_history = {emp: set() for emp in EMPLOYEES}
    # 记录每个员工的禁排日期
    emp_blocked_days = {emp: set() for emp in EMPLOYEES}
    # 每日排班结果
    daily_schedule = {day: {} for day in range(TOTAL_DAYS)}

    for day_idx in range(TOTAL_DAYS):
        current_weekday = day_idx % DAYS_PER_WEEK
        used_emps = set()

        # 优先排晚班,因为有禁排约束
        for shift in ["N", "A", "M"]:
            # 筛选符合条件的员工
            candidates = [
                emp for emp in EMPLOYEES
                if emp not in used_emps
                and day_idx not in emp_blocked_days[emp]
                and (current_weekday, shift) not in emp_shift_history[emp]
            ]

            if not candidates:
                raise ValueError(f"无法为第{day_idx+1}天的{shift}班找到合适员工,请调整排班策略")

            # 随机选择候选员工(可改为按固定顺序选择,提升稳定性)
            selected_emp = random.choice(candidates)

            # 更新记录
            daily_schedule[day_idx][shift] = selected_emp
            used_emps.add(selected_emp)
            emp_shift_history[selected_emp].add((current_weekday, shift))

            # 晚班后添加两天禁排期
            if shift == "N":
                if day_idx + 1 < TOTAL_DAYS:
                    emp_blocked_days[selected_emp].add(day_idx + 1)
                if day_idx + 2 < TOTAL_DAYS:
                    emp_blocked_days[selected_emp].add(day_idx + 2)

    return daily_schedule

def export_to_csv(schedule, filename="员工排班表.csv"):
    with open(filename, "w", encoding="utf-8-sig", newline="") as csvfile:
        writer = csv.writer(csvfile)
        # 写入表头
        writer.writerow(["日期", "星期", "早班(M)", "中班(A)", "晚班(N)"])
        for day_idx in range(TOTAL_DAYS):
            week_num = (day_idx // DAYS_PER_WEEK) + 1
            weekday = WEEKDAY_NAMES[day_idx % DAYS_PER_WEEK]
            date_label = f"第{week_num}周{weekday}"
            m_emp = schedule[day_idx]["M"]
            a_emp = schedule[day_idx]["A"]
            n_emp = schedule[day_idx]["N"]
            writer.writerow([date_label, weekday, m_emp, a_emp, n_emp])

if __name__ == "__main__":
    try:
        schedule = generate_schedule()
        export_to_csv(schedule)
        print("排班表生成成功,已保存为'员工排班表.csv'")
    except ValueError as e:
        print(f"生成失败:{e}")

注意事项

  1. 代码中使用random.choice选择员工,若出现无法找到候选的情况,可改为按固定顺序选择员工(如遍历EMPLOYEES列表取第一个符合条件的),提升排班稳定性
  2. 若需要更优的排班分布(如员工排班间隔更均匀),可调整候选员工的排序逻辑(如优先选择剩余排班次数最多的员工)
  3. 生成的CSV文件使用utf-8-sig编码,确保Excel打开时无乱码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 06:30:58