初学者练手好题——python实现设备排班

欢迎关注,敬请点赞!

排列组合——python实现设备排班

【关键字】:

  • 组合:排列中的唯一顺序(从小到大)选择结果,通常比排列的结果集少得多。

摘要:

  • python代码实现设备排班;
  • 本文使用的常用函数:(1) 列表追加:list.append() ;(2)列表排序:list.sorted() ,默认升序;
  • 本文使用的库:(1) 排列组合:import itertools

题目:

某研究室有四台高级设备需要以天为单位(周一至周日)安排轮换启用,轮换规则为:
每台设备功能相同;
每台设备每周需要启用四天;
每台设备之间启用时间不能完全相同;
周一至周五每天需要两台设备工作;
周六周日每天需要三台设备工作;
每种设备需要在周六周日中至少一天工作;
试利用编程方式计算:
1)共有多少种设备排班方案(若日期相同而分配设备不同视作同一方案,例如:
[1356, 1467, 2357, 2467][1467, 2357, 1356, 2467]视作同一方案);
2)限定每台设备均不能连续工作超过两天(例如123567671均不可),重新计算排班方案数量。

思路:

(1) 根据题意,总的工作时work_list = [1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7];
(2) 可以用4个列表分别代表4台设备,每个列表中需要有7或6;
(3) 手动枚举找规律,避免重复,按从大到小逐步夹逼,比如:

[4, 5, 6, 7], [3, 5, 6, 7], [1, 2, 4, 7], [1, 2, 3, 6];

[4, 5, 6, 7], [2, 5, 6, 7], [1, 3, 4, 7], [1, 2, 3, 6];

[4, 5, 6, 7], [1, 5, 6, 7], [2, 3, 4, 7], [1, 2, 3, 6];

(4) 写一些之后,发现仍不能写出相应的代码,也没有显著的规律,仅发现每个列表都是从[1, 2, 3, 4, 5, 6, 7]中挑出来4个元素,里面需要有7或6,同时每组4个列表拼接起来(再排序一下)的元素及其个数与总的工作时一致;
(5) 等到不想再手动枚举,让电脑来自动枚举时,自然想到排列组合,排列去重比较麻烦,组合天然就有去重属性,且运算快;
(6) 两次组合:第一次,从7个中挑出4个的组合,用“里面有7或6”筛选出初步符合的;第二次,从所有初步符合的结果集中挑出4个的组合,分配给4台设备,用“每组4个列表拼接起来与总工作时一致”再筛选一次;
(7)第二题,将第一次7选4且有7或6的初步符合结果,再用没有子集{1, 2, 3}或{2, 3, 4}或{3, 4, 5}或{4, 5, 6}或{5, 6, 7}或{6, 7, 1}或{7, 1, 2}筛选一次,接下来与第(6)步第二次一致。

  • 程序段展示:

返回顶部

import itertools

work_list = [1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7]  # 总的排班

schedule_init = []  # 初步排班
combination_init = itertools.combinations([1, 2, 3, 4, 5, 6, 7], 4)  # 抽4天工作的所有组合

for i in combination_init:
    if 6 in i or 7 in i:  # 有6或7的扩充到列表
        schedule_init.append(list(i))

schedule_second = []  # 二版排班,对四台设备进行组合
combination_second = itertools.combinations(schedule_init, 4)  # 对列表中的初步合格组合分配给4台设备,也用组合
for i in combination_second:
    if sorted(i[0] + i[1] + i[2] + i[3]) == work_list:  # 每一种组合中的列表拼接,然后排序,需要等于总排班,才是正确分配
        schedule_second.append(list(i))
        print(i)
num_exercise_1 = len(schedule_second)  # 第一题排班总数
print('第一题总数', num_exercise_1)

# 第二题:
schedule_third = []  # 三版排班,剔除对连续工作3天的情况
for i in schedule_init:
    if not (set(i).issuperset({1, 2, 3}) or set(i).issuperset({7, 1, 2}) or set(i).issuperset({6, 7, 1}) or set(
            i).issuperset({2, 3, 4}) or set(i).issuperset({3, 4, 5}) or set(i).issuperset({4, 5, 6}) or set(
        i).issuperset(
        {5, 6, 7})):  # 选择初版排班中,不包含连续工作3天的情况
        schedule_third.append(i)

schedule_final = []  # 终版,对四台设备进行组合
combination_third = itertools.combinations(schedule_third, 4)
for i in combination_third:
    if sorted(i[0] + i[1] + i[2] + i[3]) == work_list:  # 每一种组合中的列表拼接,然后排序,需要等于总排班,才是正确分配
        schedule_final.append(list(i))
        print(i)
num_exercise_2 = len(schedule_final)  # 第二题排班总数
print('第二题总数', num_exercise_2)

总结:

  • 与NBA比赛场次的安排很像,编程源于生活。

欢迎关注,敬请点赞!
返回顶部

原创文章 43 获赞 14 访问量 2872

猜你喜欢

转载自blog.csdn.net/weixin_45221012/article/details/103590082