需求背景:
某工作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