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

OR-Tools带休息间隔与休假豁免的护士排班问题建模咨询

护士排班时间间隔约束实现方案

你当前使用的布尔变量建模框架完全可以满足需求,不需要更换建模方式,只需要补充预计算逻辑和对应约束即可,具体实现步骤如下:


步骤1:预结构化班次信息

先把所有班次的时间统一转换为分钟数,避免后续重复计算时间差:

# 班次信息:key=班次编号,value=(开始时间分钟, 结束时间分钟, 是否为休息班次)
shift_info = {
    0: (0, 0, True),
    1: (480, 900, False),  # 8:00-15:00
    2: (900, 1320, False), # 15:00-22:00
    3: (480, 1320, False), # 8:00-22:00
    # 其余班次按规则补充即可
}

同时提前加好已经明确的基础约束:

# 每名员工每日仅分配1个班次
for n in all_nurses:
    for d in all_days:
        model.Add(sum(shifts[(n, d, s)] for s in all_shifts) == 1)

# 员工申请休假的日期只能排休息班次
# 假设leave_days[n]是员工n申请休假的日期列表
for n in all_nurses:
    for d in leave_days[n]:
        model.Add(shifts[(n, d, 0)] == 1)

步骤2:实现间隔约束

两次排班的间隔超过24小时的情况,必然会间隔至少1个自然日,所以我们只需要覆盖两种场景即可:

场景1:相邻两天的排班约束

预计算所有相邻天排班的非法组合:也就是前一天下班到第二天上班的间隔不在12~24小时区间的班次对,直接禁止同时出现:

invalid_adjacent_pairs = []
for s_prev in [s for s in all_shifts if not shift_info[s][2]]:
    prev_end = shift_info[s_prev][1]
    for s_curr in [s for s in all_shifts if not shift_info[s][2]]:
        curr_start = shift_info[s_curr][0]
        # 相邻天的间隔 = 1天分钟数 + 本次上班时间 - 上次下班时间
        gap = 1440 + curr_start - prev_end
        if gap < 720 or gap > 1440: # 小于12小时或大于24小时
            invalid_adjacent_pairs.append((s_prev, s_curr))

# 添加相邻天非法组合禁止约束
for n in all_nurses:
    for d in range(len(all_days)-1):
        for s_prev, s_curr in invalid_adjacent_pairs:
            model.Add(shifts[(n, d, s_prev)] + shifts[(n, d+1, s_curr)] <= 1)

场景2:间隔1天的排班约束

如果两次排班间隔1个自然日且中间没有休假,那么间隔必然超过24小时,属于非法情况,因此约束为:如果前后两天都排了非休息班次,中间那天必须是休假:

for n in all_nurses:
    for d in range(len(all_days)-2):
        for s_prev in [s for s in all_shifts if not shift_info[s][2]]:
            for s_curr in [s for s in all_shifts if not shift_info[s][2]]:
                # 仅当d和d+2天都排了非休息班次时,要求d+1天必须是休息
                model.Add(shifts[(n, d+1, 0)] == 1).OnlyEnforceIf([
                    shifts[(n, d, s_prev)],
                    shifts[(n, d+2, s_curr)]
                ])

以上逻辑已经天然支持约束2:只要两次排班中间有休假,间隔限制自动不生效。


可选替代建模方式

如果你觉得布尔变量的约束编写太零散,可以改用单整数变量代表每日班次的建模方式:每个shift_n%id%i变量的取值范围是0到最大班次编号,本质和布尔变量建模等价,约束写法会更简洁,求解效率没有明显差异。

内容的提问来源于stack exchange,提问作者Álvaro Ruiz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 06:45:05