预约调度算法(N人有N个自由忙位,约束满足)

时间:2012-06-21 17:22:55

标签: algorithm graph constraint-programming

问题陈述

我们有一个雇主想要采访N人,因此会有N个面试时段。每个人都有自由忙碌的时间表。给出一个算法,如果可能的话,将N个人调度到N个插槽中,如果不可能,则返回标志/错误/等。什么是最快的运行时复杂性?

我的方法到目前为止

天真:有N!安排N人的方法。浏览所有这些,对于每个排列,检查它是否可行。 O(n!)

回溯:

  1. 寻找任何只能有1个人的面试时段。安排此人,将其从候选人列表中删除并删除该插槽。
  2. 寻找任何只能进入1个位置的候选人。安排此人,将其从候选人列表中删除并删除该插槽。
  3. 重复1& 2直到没有更多这样的组合。
  4. 选择一个人,将他们随机安排到他们的一个可用插槽中。记住这个操作。
  5. 重复1,2,3,直到我们有一个时间表或存在无法解决的冲突。如果我们有时间表,请将其退回。如果存在无法解决的冲突,请回溯。
  6. 这是O(n!)最糟糕的情况,我认为 - 这不是更好。

    可能有D.P.解决方案 - 但我还没有看到它。

    其他想法

    问题可以用NxN矩阵表示,其中行是“槽”,列是“人”,值为“1”表示空闲,“0”表示忙。然后,我们在这个矩阵中寻找一个行列交换的Identity Matrix。步骤1& 2正在寻找只有一个“1”的行或列。 (如果矩阵的秩是= N,那表示存在解决方案。但相反的情况并不成立) 另一种看待它的方法是将矩阵视为未加权的有向图边缘矩阵。然后,每个节点代表1个候选和1个时隙。然后我们寻找一组边,以便图中的每个节点都有一个输出边和一个输入边。或者,对于2x节点,它将是一个二分图。

    矩阵示例:

    1 1 1 1
    0 1 1 0
    1 0 0 1
    1 0 0 1
    

4 个答案:

答案 0 :(得分:12)

正如您所指出的那样,问题等同于在二分图中找到最大匹配的问题(一组顶点是人的集合,另一组是插槽,一个人之间存在边缘如果此人可用于此插槽,则为一个插槽。)

使用Hopcroft-Karp algorithm可以解决此问题。

复杂性O(n ^(5/2))在最坏的情况下,如果图形稀疏则更好。

答案 1 :(得分:12)

对于约束规划方法,它可以以不同的方式建模,例如使用矩阵方法和基于集合的方法。

基于集合的方法在高级CP语言MiniZinc中显示如下。 s是每个时段可用的人(使用set notation);决策变量是数组x(每次都应分配给哪个人)。

include "globals.mzn"; 
int: n = 4;

% free persons per time slot
array[1..n] of set of int: s =  
[{1,2,3,4},
 {2,3},
 {1,4},
 {1,4}];


% decision variables
% the assignment of persons to a slot (appointment number 1..n)
array[1..n] of var 1..n: x;

solve satisfy;

constraint
  % ensure that the appointed person for the time slot is free
  forall(i in 1..n) (
    x[i] in s[i]
  )
  /\ % ensure that each person get a distinct time slot
  alldifferent(x)
;

output [ show(x) ];

该模型输出这4种解决方案(0.5ms),例如时间1被分配给人3等。

x: [3, 2, 4, 1]
----------
x: [2, 3, 4, 1]
----------
x: [3, 2, 1, 4]
----------
x: [2, 3, 1, 4]

MiniZinc模型在这里:appointment_scheduling_set.mzn

矩阵方法模型在这里(没有输出部分)并使用标准的整数编程方法:appointment_scheduling.mzn

int: n = 4;

% rows are time slots
% columns are people
array[1..n, 1..n] of int: m = array2d(1..n, 1..n,
[
1, 1, 1, 1,
0, 1, 1, 0,
1, 0, 0, 1,
1, 0, 0, 1,
]);

% decision variables
% the assignment of persons to a slot (appointment number 1..n)
array[1..n, 1..n] of var 0..1: x;

solve satisfy;

constraint
  forall(i in 1..n) (
    % ensure a free slot
    sum([m[i,j]*x[i,j] | j in 1..n]) = 1

    /\ % ensure one assignment per slot and per person
    sum([x[i,j] | j in 1..n]) = 1
    /\
    sum([x[j,i] | j in 1..n]) = 1
  )
;

此模型的解决方案是相同的,尽管以另一种(并且更详细)的方式呈现,并且 - 当它发生时 - 与基于集合的方法的顺序相同

slot 1: 3
slot 2: 2
slot 3: 4
slot 4: 1
----------
slot 1: 2
slot 2: 3
slot 3: 4
slot 4: 1
----------
slot 1: 3
slot 2: 2
slot 3: 1
slot 4: 4
----------
slot 1: 2
slot 2: 3
slot 3: 1
slot 4: 4

答案 2 :(得分:3)

这是Maximum Bipartite Matching problem

根据图表的密度,最快的解决方案可能是Hopcroft-Karp algorithm,它最多运行时间为O(N ^(5/2)),但可能要快得多。

答案 3 :(得分:2)

我相信您可以使用network flows

  • 为候选人u_i创建一个顶点i,为广告v_j创建一个顶点j
  • 创建一个源节点s并将s的(定向)边缘放置到容量为1的每个u_i
  • 制作汇聚节点t,并将每个v_j的边缘放置到容量为1的t
  • 如果候选人u_i可以在v_j位置进行采访,则可以将i的优势放到j
  • 我们有O(N)个顶点和O(N^2)条边,最大可能流程为N
  • 使用Ford-Fulkerson algorithm查找最大流量,O(E*f)需要E,其中f是边数,O(N^3)是最大流量的值,所以它需要N
  • 如果最大流量为(u_i,v_j),那么我们会有一个时间表:如果边i的流量为1,那么我们会在广告位j中与候选{{1}}进行对话,否则这是不可能的。

通过积分流定理,最大流量将在边缘上具有整数流量,即0或1,因此我们确实有一个有效的时间表。