算法思路

![Screen Shot 2019-03-17 at 12.33.49 PM](/Users/s1mple/Desktop/Screen Shot 2019-03-17 at 12.33.49 PM.png)

计算 9 段和最大所需员工总人数,此人数必定满足上一休二且早中晚均衡的规则,生成该大小的 staff_list (LinkedList);

每天抽象成早、中、晚 3 个容器;staff_list 中从头开始遍历,如果当前 staff 满足早中晚均衡条件,则将该 staff 加入容器,并将该 staff 从链表中取出放到队尾;

Staff 维护一个早中晚阶段的标志(periodFlags,Period 的 Set)。每次任命前判断该员工的 periodFlags 是否包含了当前时段。如果包含,则不满足早中晚均衡,跳过该员工迭代下一个。如果不包含,则任命该员工,并在 periodFlag 中加入当前时段。如果 periodFlags 大小等于 3(即包含了早、中、晚三个时段),则将 periodFlags 清空。

建模

DailyPlan & Container

每日计划类,包含日期 date,以及抽象的早中晚 Container 内部类。

Container 类包含:

period,早中晚阶段的枚举类

number,该阶段需要的员工人数,如第2日早上需要5人

assignedStaffs,已经任命的员工集合

主要的任命逻辑在 assign(staffs) 方法中,步骤如下:

从 staffs 该 LinkedList 中从头遍历,检查员工如果被任命后是否满足早中晚均衡的条件,如果不满足跳到下一个员工

如果满足条件,将该员工取出,加入 assignedStaffs 中并更新员工的 workPlans 记录,并将该员工放入 staffs 的队尾。退出循环,任命下一个满足条件的员工

直到 assignedStaffs 大小等于 number(全部任命完成),结束整个循环

public class DailyPlan {

private int date;

private Container morning;

private Container afternoon;

private Container night;

public void assign(LinkedList staffs) {

morning().assign(staffs);

afternoon().assign(staffs);

night().assign(staffs);

}

public class Container {

private Period period;

private int number;

private Set assignedStaffs;

public void assign(LinkedList staffs) {

while (assignedStaffs.size() < number) {

for (int i = 0; i < staffs.size(); i++) {

if (staffs.get(i).isBalancedAfterAssign(period)) {

Staff staff = staffs.remove(i);

assignedStaffs.add(staff);

staff.addWorkPlan(date, period);

staffs.addLast(staff);

break;

}

}

}

}

}

}

Staff

员工类,其中:

workPlans 记录员工都上了哪些天的什么时段的班;

periodFlags 记录员工当前上的时段的标志,在 addWorkPlan() 中如果 periodFlags 的大小等于 3(亦即包含了早中晚),就将该标识清空(保证 3 个一清空);

isBalancedAfterAssign(period) 验证如果安排当前员工工作后是否满足早中晚均衡。不满足该条件则跳过改员工,继续安排下一个;

public class Staff {

private final int id;

private final List workPlans;

private final Set periodFlags;

public boolean isBalancedAfterAssign(Period period) {

return !periodFlags.contains(period);

}

public void addWorkPlan(int date, Period period) {

if (!isBalancedAfterAssign(period)) {

throw new RuntimeException();

}

workPlans.add(new WorkPlan(date, period));

periodFlags.add(period);

if (periodFlags.size() == 3) {

periodFlags.clear();

}

}

}

Scheduling

排班调度主体类,包含:

CYCLE,周期,上一休二所以为 3

dailyPlans,每日计划的列表,包含每天什么时段需要多少人

staffs,算法思路中描述的 staff_list 链表

排班逻辑在 schedule() 方法中,步骤如下:

计算需要多少员工,根据 9 段之和最大得出

初始化 staff_list

每日安排员工上班

public class Scheduling {

private static final int CYCLE = 3;

private final List dailyPlans;

private LinkedList staffs;

public void schedule() {

int expectStaffs = expectStaffs();

staffs = initStaffList(expectStaffs);

for (DailyPlan dailyPlan : dailyPlans) {

dailyPlan.assign(staffs);

}

}

}

结果展示

先随机生成 31 的计划,每个阶段人员波动从 2 到 10

调度后将 staffs 中每个员工的排班情况打印出来

@Test

public void should_schedule_staff_correctly() {

DailyPlansGenerator generator = new DailyPlansGenerator(2, 10);

List dailyPlans = generator.generate(31);

System.out.println(generator);

Scheduling scheduling = new Scheduling(dailyPlans);

scheduling.schedule();

for (Staff staff : scheduling.staffs()) {

System.out.println(staff);

}

}

![Screen Shot 2019-03-17 at 12.22.19 PM](/Users/s1mple/Desktop/Screen Shot 2019-03-17 at 12.22.19 PM.png)

![Screen Shot 2019-03-17 at 12.22.32 PM](/Users/s1mple/Desktop/Screen Shot 2019-03-17 at 12.22.32 PM.png)

![image-20190317123311616](/Users/s1mple/Library/Application Support/typora-user-images/image-20190317123311616.png)

java旅客接口_GitHub - s1mplecc/checkin-scheduler: 使用 Java 实现的旅客人数分布预估与值机排班调度算法...相关推荐

  1. java请求接口示例_用示例解释Java接口

    java请求接口示例 介面 (Interfaces) Interface in Java is a bit like the Class, but with a significant differe ...

  2. java的接口怎么理解_如何理解Java 中的接口

    一.接口(Interface) 在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明.一个类通过继承接口的方式,从而来继承接口的抽象方法.接口并不是类,编写接口的方 ...

  3. java中接口适配器实现,12.1.8 Java中的应用-AWT事件适配器(接口的适配器模式)...

    12.1.8  Java中的应用-AWT事件适配器(接口的适配器模式) 从以上的学习我们已经了解到,基于接口的适配器模式是采用抽象化接口的方式,来达到节省接口函数的目的,这一特性特别适合于Java A ...

  4. java系统接口开发_模拟用户管理系统java接口开发与测试实战

    一.接口开发 1.引入依赖 1 2 org.springframework.boot 3 spring-boot-starter-parent 4 1.5.3.RELEASE 5 6 7 org.sp ...

  5. java 银联接口_银联接口测试——详细(JAVA)

    准备材料 1.注册账号 https://open.unionpay.com/ajweb/register?locale=zh_CN 2.▼登录账号 -->帮助中心--> 下载,选择网关支付 ...

  6. java用接口求立方体表面积_用JAVA如何画正方体 长方体

    下载一个官方3D插件: JAVA 3D API 最新j3d-1_5_2-windows-i586.exe https://java3d.dev. 安装成功就可以运行以下程序 // JFrame imp ...

  7. java 实现接口后重写方法报错

    java 实现接口后重写方法报错 java 实现接口后重写方法报错 The method contextDestroyed(ServletContextEvent) of type InitListe ...

  8. java中接口文件创建_功能接口简介–在Java 8中重新创建的概念

    java中接口文件创建 世界各地的所有Java开发人员都将至少使用以下接口之一:java.lang.Runnable,java.awt.event.ActionListener,java.util.C ...

  9. AliPay - Java支付宝接口开发(三)

    一.前言 AliPay - Java支付宝接口开发(一) AliPay - Java支付宝接口开发(二) 二.支付宝沙箱环境集成Web项目 1.将支付宝Demo中的相关文件复制到我们的项目中 1.1 ...

最新文章

  1. ubuntu16创建开机启动服务
  2. CocoStudio 1.3和1.4.1导入Flash文件注意事项(转载并有修改)
  3. php empty();和isset();
  4. Java IO: 并发IO
  5. mysql两张主表person event加上第三张关联表
  6. 最短编辑距离问题 : Levenshtein Distance
  7. 数据科学 IPython 笔记本 9.11 结构化数据:NumPy 的结构化数组
  8. ansible基本模块-copy
  9. 《简明python教程》_简明Python教程
  10. oracle 修改表字段的长度
  11. 计算机相关专业的学生如何规划自己的职业?
  12. 欧姆龙OMRON CP1H  PLC与台达 DOP-B触摸屏通讯
  13. 商业模式及其 SubDAO 深入研究
  14. [经验教程]2022网线水晶头插座接头排线接线顺序与方法图解
  15. 操作系统-进程互斥的软件实现方法
  16. 曾經的文字﹐曾經的歲月
  17. linux 多核cpu监控,Linux 下多核CPU知识
  18. mv150us无线网卡驱动linux,水星MW150US2.0驱动-水星MW150US无线网卡驱动下载v2.0 官方最新版-西西软件下载...
  19. 非标资产与标准资产_资产商店行动新闻– 2011年10月!
  20. IOS Label下划线 中划线

热门文章

  1. 几种特种印花方式简介
  2. 7、【转载】python yield generator 详解
  3. 小程序wx.getRecorderManager()录音管理
  4. 兴业太阳能:将“绿色能源”带到国外
  5. Eclipse热部署JSP
  6. Coding List
  7. 23_触发器_库存与订单实战
  8. 2013年微软编程之美大赛初赛第二题(博客园居然可以插入代码!!)
  9. Microsoft SQL 2000 错误代码(一)
  10. 华为机试HJ76:尼科彻斯定理