分配算法/可用性算法

时间:2014-12-29 17:23:46

标签: java algorithm

我想知道是否有人知道我可以用来帮助我解决以下问题的算法:

将人(n)分配给某些事件(m),m只能附加一个人,并且每次必须随机化(如果只有一个选项可用,则允许相同的人(n))。 n具有可用时间和可用日期等属性。要使n与m匹配,可用时间和可用日期必须匹配n和m。可以有多个n匹配m的时间,但它必须是最合适的,因此可以分配m的其余部分。下面的图表很可能更好地解释它(抱歉)。 n可以分配到一个以上的m,但应该公平地完成,使得一个n不具有所有可用的m enter image description here

正如您所看到的,人员A可以附加到事件A,但由于需要将它们全部匹配(最佳匹配尝试),因此附加到事件B以允许将人员C分配给事件A和人员B到事件C。

我只是想知道是否有人知道这类问题的名称以及我如何解决它,我正在用Java编写程序

3 个答案:

答案 0 :(得分:1)

这是Max Flow Problem的变体。有很多算法可以解决最大流问题,包括The Ford-Fulkerson Algorithm或其细化Edmonds-Karp Algorithm。一旦您能够将问题更改为最大流量问题,解决它就非常简单。但最大流量问题是什么?

该问题采用加权有向图并询问问题"可以从源(节点)引导到接收器(另一个节点)的最大流量是多少?" 。 当将图形视为水流网络时,存在一些具有逻辑意义的约束。

  1. 通过每条边的流量必须小于或等于"容量"图表中每个边缘的边缘(权重)。它们也必须是非负数。
  2. 流入每个节点的流量必须等于除源和接收器之外的任何节点离开该节点的流量。流经节点的流量没有限制。
  3. 考虑以下图表,其中s为源,t为接收器。

    enter image description here

    最大流量问题的解决方案是总流量为25,流量如下:

    enter image description here

    将问题转换为最大流量问题很简单。假设您的输入是:

    • N人,以及有关人员p_i何时可用时间和日期的相关信息。
    • M有时间和地点的活动。

    创建具有以下属性的图表:

    • 超级来源s
    • N个人节点p_1 ... p_n,容量infinity的边缘将所有s p_i连接到i in 1 ... n
    • 超级汇t
    • M个事件节点e_1 ... e_m,容量1的边缘将e_i连接到t所有i in 1 ... m
    • 对于某个人和事件(p_i, e_j)的每个组合,容量infinityp_i连接到e_j iff p的边缘可以有效地参加活动{{ 1}}(否则没有边缘连接ep_i)。

    构建这些规范的图表有e_j运行时。

    对于您的示例,构造的图形将如下所示(未标记的边缘具有容量无穷大):

    enter image description here

    您已正确注意到此示例中存在值为O(1) + O(N) + O(N) + O(M) + O(M) + O(1) + O(NM) = O(NM)的最大流量,并且任何最大流量都将返回相同的值。一旦您可以执行此转换,您就可以运行任何最大流算法并解决您的问题。

答案 1 :(得分:0)

创建一个名为AllocatePerson的类,其中包含一个Person和一个名为Events的事件列表,名为lsInnerEvents(您必须首先定义Person类和事件类,两者都包含Time和Day列表。)

在AllocatePerson的构造函数中,您提供了一个Person和一个事件列表,构造函数将循环思考事件,并将只添加与Person参数匹配的内容列表。

主代码将为每个Person(当时为1)创建一个AllocatePerson,实现以下逻辑:

如果新创建的对象“objAllocatePerson”具有size = 1的lsInnerEvents列表,则从要分配的事件列表中删除lsInnerEvents中包含的元素,并将触发一个名为MaintainEvents(Events removedEvents)的过程,传递分配的事件(一个在lsInnerEvents内。

函数MaintainEvents将遍历当前的AllocatePersons数组,并从lsInnerEvents中删除“removedEvents”,如果之后lsInnerEvents的大小为= 1,它将以新删除的事件递归调​​用MaintainEvents(),并删除要分配的主要事件列表中的新lsInnerEvents。

在执行结束时,您将通过循环遍历AllocatePersons数组来获得所有关联,其中lsInnerEvents大小为1

答案 2 :(得分:0)

您可以考虑的方法如下:

  1. 事件创建Java对象。
  2. 将所有事件放入池(Java集合)
  3. 让每个从池中选择事件。由于每个人只能选择特定日期的事件,因此创建一个事件的子集,该子集将位于池中,以便从中进行选择。
  4. 事件添加必要的属性,以确保只能由

    选择一次