我想知道是否有人知道我可以用来帮助我解决以下问题的算法:
将人(n)分配给某些事件(m),m只能附加一个人,并且每次必须随机化(如果只有一个选项可用,则允许相同的人(n))。 n具有可用时间和可用日期等属性。要使n与m匹配,可用时间和可用日期必须匹配n和m。可以有多个n匹配m的时间,但它必须是最合适的,因此可以分配m的其余部分。下面的图表很可能更好地解释它(抱歉)。 n可以分配到一个以上的m,但应该公平地完成,使得一个n不具有所有可用的m
正如您所看到的,人员A可以附加到事件A,但由于需要将它们全部匹配(最佳匹配尝试),因此附加到事件B以允许将人员C分配给事件A和人员B到事件C。
我只是想知道是否有人知道这类问题的名称以及我如何解决它,我正在用Java编写程序
答案 0 :(得分:1)
这是Max Flow Problem的变体。有很多算法可以解决最大流问题,包括The Ford-Fulkerson Algorithm或其细化Edmonds-Karp Algorithm。一旦您能够将问题更改为最大流量问题,解决它就非常简单。但最大流量问题是什么?
该问题采用加权有向图并询问问题"可以从源(节点)引导到接收器(另一个节点)的最大流量是多少?" 。 当将图形视为水流网络时,存在一些具有逻辑意义的约束。
考虑以下图表,其中s
为源,t
为接收器。
最大流量问题的解决方案是总流量为25,流量如下:
将问题转换为最大流量问题很简单。假设您的输入是:
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)
的每个组合,容量infinity
将p_i
连接到e_j
iff p
的边缘可以有效地参加活动{{ 1}}(否则没有边缘连接e
和p_i
)。构建这些规范的图表有e_j
运行时。
对于您的示例,构造的图形将如下所示(未标记的边缘具有容量无穷大):
您已正确注意到此示例中存在值为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)
您可以考虑的方法如下:
为事件添加必要的属性,以确保只能由人
选择一次