排岗实例代码

现有实习生若干,正式员工若干。需要进行实验室值班。

条件1:白天8轮岗,夜晚6轮岗。
条件2:白班每班需要两个人值班(称之为流动班),夜晚需要三个人值班(有一人需在工位等待,称之为坐班。其他俩人为流动班)。
条件3:实习生自己不能单独在流动班,需要正式员工陪同。|
条件4:一个人不能同一天轮到三次班。
条件5:白天不能站两班,晚上不能站两班。
条件6:一周内,同一个人尽量不能同一个时间班。
条件7:每个人都得坐班。
条件8:白班的下午值班过的人,不能再值夜班
条件9:值夜班的人,不能值第二天上午的班。
条件10:不能连续两天同一个人值夜班
条件11:科室可能会发生人员变动
条件12:读取名单表,根据名单表排序
条件13:人员变动后也需要输出排班情况
条件14:每个人的排岗次数之差不能大于2次

部分实例代码:

import random

import pandas as pd

# 读取 CSV 文件

file_path = "people_names.csv"  # 

data = pd.read_csv(file_path)

# 假设 CSV 文件中有两列:老人 和 新人,分别表示老人的名字和新人的名字

seniors = data['Elderly'].dropna().tolist()  # 删除空值并转换为列表

newbies = data['Newcomers'].dropna().tolist()  # 删除空值并转换为列表

# 合并所有人员

all_people = seniors + newbies

# 一周时间

days = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"]

# 初始化值班表

schedule = []

# 初始化轮值记录和总排岗次数记录

inner_shift_tracker = {person: 0 for person in all_people}  # 

total_shift_tracker = {person: 0 for person in all_people}  # 总排岗记录

# 最大排岗次数限制

MAX_SHIFTS = 11

# 函数:分配白天的班次(严格遵守外班规则和排岗限制)

def assign_day_shifts(people, day):

    day_shifts = []

    white_shifted = []  # 用来记录当天排了白班的人员

    for round_num in range(8):  # 每天8轮白班

        print(f"\n------ {day} 白班 第 {round_num + 1} 轮 ------")

        # 筛选未达到最大班次限制的候选人

        valid_people = [p for p in people if total_shift_tracker[p] < MAX_SHIFTS]

        print(f"有效的候选人: {valid_people}")

        # 确保每轮有至少1名老人

        seniors_available = [p for p in valid_people if p in seniors]

        newbies_available = [p for p in valid_people if p in newbies]

        if len(seniors_available) < 1:

            raise ValueError(f"无法满足白班外班规则(至少1名老人),当前可用老人不足!")

        # 优先选择1位老人和1位新人,如果新人足够

        if len(newbies_available) > 0:

            senior = seniors_available[0]  # 选择1位老人

            newbie = random.choice(newbies_available)  # 随机选择1位新人

            shift = [senior, newbie]

        else:

            # 如果没有足够的新人,则选择2位老人

            if len(seniors_available) >= 2:

                shift = random.sample(seniors_available, 2)  # 两人均为老人

            else:

                raise ValueError("没有足够的老人分配班次!")

        # 更新总排岗次数

        for person in shift:

            total_shift_tracker[person] += 1

        # 打印分配结果

        print(f"分配的人员: {shift}")

        # 添加到班次表,并移除已分配人员

        day_shifts.append(shift)

        white_shifted.extend(shift)  # 记录已经排白班的人员

        people = [p for p in people if p not in shift]

        # 打印已分配白班的人员

        print(f"已排白班的人员: {white_shifted}")

    return day_shifts, white_shifted

# 分配班次

for day in days:

    people_for_day = all_people[:]  # 每天重置人员列表

    day_shifts, white_shifted = assign_day_shifts(people_for_day, day)

    night_shifts = assign_night_shifts(people_for_day, day, white_shifted)

    for i, shift in enumerate(day_shifts):

        schedule.append([day, "白天", i + 1, "无", shift[0], shift[1]])

    for i, shift in enumerate(night_shifts):

        schedule.append([day, "晚上", i + 1, shift[0], shift[1], shift[2]])

# 转换为 DataFrame

columns = ["日期", "班次类型", "班次编号", "内班", "流动班1", "流动班2"]

df_schedule = pd.DataFrame(schedule, columns=columns)

# 生成排班表之后,交换排班次数最多的人的班次

def balance_shift_distribution(schedule, total_shift_tracker, max_shifts=9):

    # 获取总排班次数最多和最少的人

    max_shifts_person = max(total_shift_tracker, key=total_shift_tracker.get)

    min_shifts_person = min(total_shift_tracker, key=total_shift_tracker.get)

    while total_shift_tracker[max_shifts_person] > max_shifts:

        # 找到排班次数最多的人和排班次数最少的人

        max_shifts_person = max(total_shift_tracker, key=total_shift_tracker.get)

        min_shifts_person = min(total_shift_tracker, key=total_shift_tracker.get)

        # 找出排班次数最多的人的班次,并进行交换

        for shift in schedule:

            if max_shifts_person in shift[4:] and min_shifts_person not in shift[4:]:

                # 找到包含最多排班人员的班次,并将其与最少排班人员的班次交换

                shift[4:] = [min_shifts_person if person == max_shifts_person else person for person in shift[4:]]

                total_shift_tracker[max_shifts_person] -= 1

                total_shift_tracker[min_shifts_person] += 1

                break  # 交换完一个班次后就跳出

    return schedule

# 在生成排班表之后调用函数

schedule = balance_shift_distribution(schedule, total_shift_tracker)

# 转换为 DataFrame

df_schedule = pd.DataFrame(schedule, columns=columns)

# 保存为 Excel

output_file = "A1.xlsx"

df_schedule.to_excel(output_file, index=False)

print(f"值班表已生成并保存到 {output_file}")

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刘瑞瑞rr

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值