// 构造函数 public Table(PersonStream ps) { reallytimeUpperbound = new double[7] { 2.0f, 1.0f, 2.0f, 2.0f, 1.5f, 2.0f, 4.0f }; timeUpperbound = new int[7] { 4, 3, 3, 3, 3, 2, 4 }; weekendPersonbound = new int[3] { 2, 2, 4 }; weekendUpperbound = new double[3] { 5.0f, 5.5f, 4.0f }; // 对每天 for (int i = 0; i < 5; i++) { iTable.Add(new List<Cell>()); // 对每个时段 for (int j = 0; j < 7; j++) { Cell p1 = new Cell((TimePeriod)(i * 7 + j)); p1.upperbound = timeUpperbound[j]; // 找可填入的人 for (int k = 0; k < ps.pstream.Count; k++) { for (int m = 0; m < ps.pstream[k].validTimePeriod.Count; m++) { if (ps.pstream[k].validTimePeriod[m] == p1.cid) { p1.candidate.Add(ps.pstream[k]); break; } } } iTable[i].Add(p1); } } }
// 核心算法:寻找排班的解 public string Dash(out string pt, out bool vl) { // 获得一份排班时间表的拷贝 List<Cell> proc = new List<Cell>(); for (int i = 0; i < myTable.iTable.Count; i++) { for (int j = 0; j < myTable.iTable[i].Count; j++) { proc.Add(myTable.iTable[i][j]); } } // 将格子从可用人数从小到大排序 proc.Sort((x, y) => { if (x.candidate.Count - x.upperbound < y.candidate.Count - y.upperbound) { return -1; } else if ((x.candidate.Count - x.upperbound == y.candidate.Count - y.upperbound) && x.candidate.Count < y.candidate.Count) { return -1; } else if (x.candidate.Count - x.upperbound > y.candidate.Count - y.upperbound) { return 1; } else { return 0; } }); // 迭代搜索解 foreach (Cell c in proc) { // 对每个格子的候选人做排序 c.candidate.Sort((x, y) => { // 0:如果此人已满直接逆向调整 if (x.isOK() == true) { return 1; } // 1:优先排可用时间少的人 if (x.validTimePeriod.Count < y.validTimePeriod.Count) { return -1; } else if (x.validTimePeriod.Count == y.validTimePeriod.Count) { // 2:优先排已有时间少的人 if (x.currentTime < y.currentTime) { return -1; } else if (x.currentTime == y.currentTime) { // 3:优先排B组 if (x.groupType == GroupType.B && y.groupType != GroupType.B) { return -1; } // 4:优先排A组 else if (x.groupType == GroupType.A && y.groupType != GroupType.A) { return -1; } // 5:最后再考虑C组,但不改变顺序 else { return 0; } } // 逆向调整 else { return 1; } } // 逆向调整 else { return 1; } }); // 标记并更新 if ((int)c.cid % 7 == 0 && c.cid < TimePeriod.SAT1) { // A不行 if (((int)c.cid / 7) % 2 == 0) { int encounter = 0; for (int i = 0; i < c.candidate.Count; i++) { if (c.candidate[i].isOK() != true && c.candidate[i].groupType != GroupType.A) { c.candidate[i].currentTime += Table.reallytimeUpperbound[(int)c.cid % 7]; c.currentList.Add(c.candidate[i]); encounter++; } if (encounter >= c.upperbound) { break; } } } // B不行 else { int encounter = 0; for (int i = 0; i < c.candidate.Count; i++) { if (c.candidate[i].isOK() != true && c.candidate[i].groupType != GroupType.B) { c.candidate[i].currentTime += Table.reallytimeUpperbound[(int)c.cid % 7]; c.currentList.Add(c.candidate[i]); encounter++; } if (encounter >= c.upperbound) { break; } } } } else { int encounter = 0; for (int i = 0; i < c.candidate.Count; i++) { if (c.candidate[i].isOK() != true) { c.candidate[i].currentTime += Table.reallytimeUpperbound[(int)c.cid % 7]; c.currentList.Add(c.candidate[i]); encounter++; } if (encounter >= c.upperbound) { break; } } } } // 接下来排周六日 List<Cell> weekend = new List<Cell>(); for (int i = 0; i < 6; i++) { Cell nc = new Cell((TimePeriod)35 + i); nc.upperbound = Table.weekendPersonbound[i % 3]; weekend.Add(nc); } for (TimePeriod t = TimePeriod.SAT1; t <= TimePeriod.SUN3; t++) { for (int i = 0; i < myStream.pstream.Count; i++) { for (int j = 0; j < myStream.pstream[i].validTimePeriod.Count; j++) { if (myStream.pstream[i].validTimePeriod[j] == t) { weekend[(int)t - (int)TimePeriod.SAT1].candidate.Add(myStream.pstream[i]); } } } } // 迭代搜索 foreach (Cell c in weekend) { c.candidate.Sort((x, y) => { if (x.currentTime < y.currentTime) return -1; else if (x.currentTime == y.currentTime) return 0; else return 1; }); // 标记并更新 int encounter = 0; for (int i = 0; i < c.candidate.Count; i++) { if (c.candidate[i].currentTime + Table.weekendUpperbound[((int)c.cid % 7) % 3] < Table.cynthia && c.candidate[i].groupType == GroupType.C) { c.candidate[i].currentTime += Table.weekendUpperbound[((int)c.cid % 7) % 3]; c.currentList.Add(c.candidate[i]); encounter++; } if (encounter >= c.upperbound) { break; } } for (int i = 0; i < c.candidate.Count && encounter < c.upperbound; i++) { if (c.candidate[i].currentTime + Table.weekendUpperbound[((int)c.cid % 7) % 3] < Table.cynthia && c.candidate[i].groupType != GroupType.C) { c.candidate[i].currentTime += Table.weekendUpperbound[((int)c.cid % 7) % 3]; c.currentList.Add(c.candidate[i]); encounter++; } } } foreach (Cell c in weekend) { proc.Add(c); } // 时间少的排到前面 foreach (Person p in myStream.pstream) { myStream.pstream.Sort((x, y) => { if (x.currentTime < y.currentTime) return -1; else if (x.currentTime > y.currentTime) return 1; else return 0; }); } // 处理输出信息 string str = ""; string cel = ""; foreach(Person p in myStream.pstream) { str += p.name + "\t" + p.groupType.ToString() + "\t" + p.currentTime.ToString() + Environment.NewLine; } proc.Sort((x, y) => { if (x.cid < y.cid) return -1; else if (x.cid > y.cid) return 1; else return 0; }); foreach(Cell c in proc) { cel += c.cid.ToString() + "\t"; foreach (Person p in c.currentList) { cel += p.name + p.groupType.ToString() + "\t"; } cel += Environment.NewLine; if ((int)(c.cid + 1) % 7 == 0) { cel += Environment.NewLine; } } pt = str; vl = this.isValuable(proc); return cel; }