【Python】计算最少排班人数(1)

需求背景:

某工作24小时需要人员,单个班次为8或9小时,需要根据每小时需要的人数、不同的班次计算最低需要的人数。

每小时需要的人数举例:

班次类型:

问题分析:

1、需要各个时段的人员数大于等于需要的人数

2、为了减少计算量,可以先设置每次时段各个班次的人数不大于时段的所需人数,比如8:00-8:59时段,需要4个人,那覆盖这个时段的每中班次顶多也就4个人

程序设计:

1、采取穷举法计算所有情况,并计算满足需求的方案里,需要人数最少得方案

2、为了减少计算量,先随机一定量的方案(比如100种),求这些方案里最小所需人数(X),穷举时大于X的方案直接跳过不验证

3、根据全天时段里需要人数的最大值,小于该值的方案直接跳过不验证,比如上方截图中,16:00-16:59时段需要人数最多(40人),那么低于40的肯定无法满足需求,直接不验证

部分关键代码及方法:

班次类型设置:
ban_list=[
    '常班1(8:00-17:00)',
    '常班2(10:00-19:00)',
    '常班3(11:00-20:00)',
    '晚班1(12:00-21:00)',
    '晚班2(14:00-23:00)',
    '小夜1(16:00-01:00)',
    '小夜2(18:00-03:00)',
    '大夜1(20:00-05:00)',
    '小夜2(23:00-08:00)',
    '早班(06:00-15:00)',
]
ban_hour=[
    [0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0],
    [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1],
    [1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1],
    [1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1],
    [1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
    [0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0],
]
验证排班是否满足需求:
def check(need,do):
    #小时所需人数(24长度的list)+实际人数(24长度的list)
    if_can=1
    for i in range(len(need)):
        if do[i]<need[i]:
            if_can=0
    return if_can
随机方案选取:
def ran_choice(l,cnt):
    ran_l=[]
    x=[]
    for j in range(cnt):
        for i in range(len(l)):
            x.append(random.randint(a=0,b=l[i]))
        ran_l.append(x)
        x=[]
    return ran_l

ran=hc_random.ran_choice(ban_type_max,int(max_hc)*10)
记录满足需求的方案
def sele(hc_list,need,banci):
    hc_list_yes=[]
    if_enough=0
    for i in range(len(hc_list)):
        does=do_hc(banci,hc_list[i])
        if_enough=check(need, does)
        if i%1000000==0:
            print(i)
        if if_enough==1:
            hc_list_yes.append(hc_list[i])
        if_enough = 0
    return hc_list_yes
每个班次最大人数下,所需人力
def ban_max(need,l):
    ban_cnt=0
    ban_maxhc=[]
    for i in range(len(l)):
        for j in range(len(l[i])):
            if l[i][j]!=0:
                ban_cnt=max(ban_cnt,need[j]/l[i][j])
        ban_maxhc.append(ban_cnt)
        ban_cnt=0
    return ban_maxhc
所有方案列举记录,但不记录高于随机选取方案人数的方案和低于最高时段需求人数的方案:
def all_(max_hc,hour_sel,cur_y_idx=0,l_tmp=[],l_res=[]):
    ban_t=len(max_hc)-1
    for x_idx in range(int(max_hc[cur_y_idx])+1):
        l_tmp.append(x_idx)
        if cur_y_idx == ban_t:
            if  sum(l_tmp)>=int(hour_sel[0]) and min(l_tmp)>=int(hour_sel[1]) and sum(l_tmp)<=int(hour_sel[2]):
                l_res.append([*l_tmp])
        else:
            all_(max_hc,hour_sel, cur_y_idx+1, l_tmp, l_res)
        l_tmp.pop()
    return l_res

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值