某研究室有四台设备需要以天为单位(周一至周日)安排轮换启用(排班问题)

题目

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

分析

     1   2   3   4   5   6   7   sum
d1   -   -   -   -   -   -   -    4
d2   -   -   -   -   -   -   -    4
d3   -   -   -   -   -   -   -    4
d4   -   -   -   -   -   -   -    4
sum  2   2   2   2   2   3   3
  1. 根据题意,可转为上述模型,中间区域一共28个位置,每个位置为0或1,1代表设备启用
    因此将问题转换为在28个位置中插入16个1,12个0,即0与1的分配问题
  2. 每台设备周六日最少启用一天,则可以分为两种情况:
    周一至周五启用两天,周六日启用两天
    周一至周五启用三天,周六日启用一天

代码实现(python)

代码仅实现功能,未考虑性能,仅供参考

实现:

from itertools import combinations
import numpy as np

# 一台设备一周的排班方案
one_dev_plan = list()
# 周1~5 - 索引
mon_to_fri = [0, 1, 2, 3, 4]
# 周1~5任选两天再加周六周日的组合方案
two_and_two = list(combinations(mon_to_fri, 2))
for plan in two_and_two:
    one_dev_plan.append(plan + (5, 6))
# 周1~5任选三天再加周六日中的一天的组合方案
three_and_one = list(combinations(mon_to_fri, 3))
for plan in three_and_one:
    one_dev_plan.append(plan + (5,))
    one_dev_plan.append(plan + (6,))
# 设备一周的排列情况中选出4种作为四台设备一周的排列情况
four_dev_plan = list(combinations(one_dev_plan, 4))

# result_1 - 第一问结果,list_28 - 28个位置的0、1排列
result_1, list_28 = list(), list()
# 周一至周五每天需要两台设备工作,周六周日每天需要三台设备工作
tar_arr = np.array([2, 2, 2, 2, 2, 3, 3])
# t_indices:((0, 3, 5, 6), (0, 2, 3, 5), (0, 2, 4, 5), (1, 2, 3, 5))
for t_indices in four_dev_plan:
    for indices in t_indices:
        # 一台设备一周的0、1排列
        dev_list = np.zeros(7)
        dev_list[list(indices)] = 1
        list_28.append(dev_list)
    # list_28转换成ndarray数组,便于列相加操作
    arr_28 = np.array(list_28)
    col_sum = np.sum(arr_28, axis=0)
    # 若符合tar_arr条件,则为要求的排班方案
    if (col_sum == tar_arr).all():
        result_1.append(arr_28)
    list_28.clear()
# for i, plan in enumerate(result_1):
#     print(plan, "<- 方案{}".format(i + 1))
# print("-" * 50)

print("1)共有{}种设备排班方案.".format(len(result_1)))
print("*" * 50)

# 第二问结果
result_2 = list()
add = True
for plan in result_1:
    for dev in plan:
        # 设备出现连续启用三天的情况
        if 3 in (
                dev[0] + dev[1] + dev[2], dev[1] + dev[2] + dev[3],
                dev[2] + dev[3] + dev[4], dev[3] + dev[4] + dev[5],
                dev[4] + dev[5] + dev[6], dev[5] + dev[6] + dev[0]
        ):
            add = False
            break
    if add:
        result_2.append(plan)
    add = True
# for i, plan in enumerate(result_2):
#     print(plan, "<- 方案{}".format(i + 1))
# print("-" * 50)

print("2)共有{}种设备排班方案.".format(len(result_2)))

运行结果:

1)共有150种设备排班方案.
**************************************************
2)共有4种设备排班方案.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值