我正在开发一个应用程序,我需要在轮换时间表上为成员自动安排作业。我不太擅长解释规则,所以这里有一些数据可以帮助解决:
职位:职称,每周一至周三等规则
类别:一组职位
团体:另一组职位。同一组中的职位不能在同一天分配
成员:在指定日期分配到职位的用户。
对于当月的每个日期,成员被分配到职位(均按升序排列)。如果成员被分配到一个类别中的某个职位,则下一次出现同一类别中的职位时,将按字母顺序(或列表的开头)分配下一个成员,例如。
成员:M1,M2,M3,M4
C1类中的位置:P1,P2,P3
位置P1的成员:M1,M2,M3,M4
位置P2的成员:M1,M2,M3
位置P2的成员:M1,M3,M4
如果为P1分配了M1,如果接下来是P2,则将分配M2。引入了额外的复杂层,如果P3接下来,则M3被分配。系统必须跟踪M2被“跳过”的事实并在下一次分配M2(如果可用),然后分配M4,或者等到它到达M2可用的位置(当有许多'被跳过时,这变得更加复杂'成员)。
如果一名成员表示他将无法在该日期上任,那么该成员也将被跳过。系统需要优先考虑跳过的成员,在它们出现时以某种方式识别它们,然后跳转到列表中的下一个逻辑人员。由于日期冲突,跳过也适用于群组。
我已经有了一个临时[和凌乱]的解决方案,我不再理解,即使我在其中有很多评论解释每一步。它的弱点在于与被跳过的成员打交道。
如果您打算对此进行编码,您会怎么做?我在PHP中实现它,但伪代码也可以。
答案 0 :(得分:6)
我的解决方案: 您需要一个PriorityQueue(在SplPriorityQueue下可以在PHP中使用)。 PriorityQueue为您提供具有降序优先级的元素(按值排序,最小值 值具有最高优先级。)
每个成员都获得一个指定的值。此值是一个带有n位数的ASCII数字(为方便起见,您可以使用8位数字),在n个位置填充零。之后你追加 名字。您还可以向每个成员添加可用职位
所以(n = 5):
这样可以轻松按优先级和名称对成员进行排序。
的制备:将
阳光灿烂的日子。您正在检索指定的位置和给定日期的类别。每个成员都加载在一个长列表中。没有出现在工作中的每个成员都没有加载,但是他的价值减去了两个。鲍勃不在这里,所以它的新值达到99997Bob。这意味着下次将自动选择Bob。 所有其他成员的价值减去了一个。
映射为特定日期分配的位置(使用SplObjectStorage):
P1-> M1,M2,M3,M4等 P2->等
地图仅包含今天必须分配的位置。
之后过滤器: 您必须查找组并删除地图上今天无法分配的任何位置。你的小组描述有点不清楚。
分配:
注意事项:
答案 1 :(得分:1)
UFF。我不跟你描述,但在类似的情况下我用sql来解决这类问题。如果你使用PHP我猜你有可用的SQL。
我建议做的是找到一种方法将这些信息存储到一组表中,然后确定sql查询为您提供所需的答案。通常,在sql中执行它比在过程语言中更简单。
例如,对于跳过的部分,您可能有一个列,记录上次分配某人的时间,然后按此顺序(以便您选择长时间未分配的人)。或者,您可以按列跳过次数并按此顺序排序。
答案 2 :(得分:0)
据我所知,有'm'成员和'n'职位。
类别:一组职位 - 在该类别中被分配一个职位的成员不能拥有另一职位?
组:一组职位 - 同一组中的职位必须在不同的日期分配。
最后,一个职位有一个可以填补它的成员列表。
从数据结构的角度来看,将成员放在一个链表中 - 每个成员必须有一个额外的[position,day]列表,它们最终被分配。然后,对于每个位置,都有一个可以填充该位置的成员的引用列表。将类别实现为另一个职位的参考列表,以确定其所在的类别。
实际分配:让一天计数器= 0,并迭代这些位置。对于每个位置P,迭代可以填充它的成员。如果出现以下情况,成员M可以填补该职位:
如果他可以填充该位置,则[position,day]对被添加到该成员,并且该成员的节点被移动到列表的END(这就是为什么需要引用的原因 - 所有引用仍然有效即使节点移动了)。这确保了'跳过的'成员被赋予最高优先级,而未被到达的成员被赋予次优先级。
填补职位后,转到下一个职位。如果该位置共享一个已经分配了位置的组,则跳过它,遍历所有位置,直到您可以在第1天分配尽可能多的位置。然后,增加日期计数器并重复第2天。这应该给你所有工作的最大分配(不确定最大值)。
提示:当一个成员移动到成员列表的末尾时,为了防止必须遍历列表,保持对结尾的引用 - 对于下一个位置,你需要从头开始,所以没有指出整个过程。