生成时间表 - 需要良好的算法

时间:2011-08-29 07:34:24

标签: c# algorithm f#

昨天在试图入睡时,我开始考虑如何解决下面的问题并意识到我无法想出一个好的算法。这不是学校作业,即使它看起来像一个,我只是想找到答案。 :)

基本上让我们想象一下商店员工的工作安排。该计划应根据一系列要求生成计划建议。

要求是:

  • 每周只有一名员工工作。
  • 员工连续两周无法工作。
  • 应该有办法防止员工入职 预定工作一周(假期)。
  • 分配应尽可能均匀,即如果我们有 员工A,B和C他们应该大致相同 周休假和那几周应该平均分配 可能的。

攻击此问题的最佳方法是什么?也许函数式编程更适合解决这个问题?

编辑:现在我知道这类问题被称为“资源约束调度”。由于“调度”通常指的是诸如计划任务或线程之类的事情,因此对此有点困难。对于那些仍然认为我要求提供家庭作业解决方案的人(尽管我明确地声称上面提到了其他问题),你可以查看我以前的问题,我认为他们清楚地表明我不是学生......

2 个答案:

答案 0 :(得分:5)

前两点是问题的约束。 第三点表示对候选解决方案进行排序的方法,如果您将其正式化,则会出现优化问题。实际上,您正在尝试最小化工作分布的差异。

请注意,由于约束,问题可能没有可接受的解决方案。

这是一个组合优化问题,您可以使用整数线性规划方法或大致使用随机局部搜索方法(它们也称为元启发式或许多其他名称)来解决它,例如遗传算法,模拟退火,禁忌搜索,迭代局部搜索,蚁群优化等。

这类特殊问题被称为作业调度,有很多关于它的文献有很多变种。

如果这不是作业,我认为这应该足以满足你的好奇心,如果我认为我告诉你你可以看到什么。

答案 1 :(得分:2)

即使看起来好像这是家庭作业,我也更愿意相信你。

以下是我的想法:

let rec assignWork n upTo last workers =
    if n <= upTo then
        let checkNameIsEqualToLast =
            match last with
            | Some n -> ((=) n)
            | _ -> fun _ -> false
        let (name, _, _) as worker =
            workers
            |> List.filter (not << fun (name, _, v) -> checkNameIsEqualToLast name || List.exists ((=) n) v)
            |> List.sortBy (fun (_, w, _) -> w)
            |> List.head
        workers
        |> List.map (function
            | n, w, v when n = name -> n, w + 1, v
            | w -> w)
        |> assignWork (n + 1) upTo (Some name)
        |> fun t -> name::t
    else []

例如:

let workers =
    List.zip
        [ 'A' .. 'E' ]
        [
            []
            [ 2 .. 4 ]
            [ 3 .. 5 ]
            [ 1 .. 10000 ]
            [ 3 ]
        ]
    |> List.map (fun (c, v) -> c, 0, v)

assignWork 1 16 None workers

输出(对我来说似乎合理):

val it : char list =
  ['A'; 'C'; 'A'; 'E'; 'B'; 'C'; 'B'; 'E'; 'A'; 'B'; 'C'; 'E'; 'A'; 'B'; 'C'; 'E']