【问题标题】:Generating schedules - need good algorithm生成时间表 - 需要好的算法
【发布时间】:2011-08-29 07:34:23
【问题描述】:

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

基本上让我们想象一下商店员工的工作时间表。程序应根据一组要求生成进度建议。

要求是:

  • 每周只有一名员工工作。
  • 员工不能连续工作两周。
  • 应该有一种方法可以防止员工获得 计划在某个星期(假期)工作。
  • 分布应尽可能均匀,即如果我们有 员工 A、B 和 C 他们应该得到大致相同的金额 数周的休息时间,这些周应均匀分布 可能。

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

编辑:现在我知道这类问题被称为“资源受限调度”。这有点难以理解,因为“调度”通常指的是调度任务或线程之类的东西。对于仍然认为我在寻求家庭作业解决方案的人(尽管我在上面明确声明),您可以查看我以前的问题,我认为它们清楚地表明我不是学生...

【问题讨论】:

  • 贪婪:使用 PriorityQueue 应该是一个很好的启发式方法,但如果某个员工在最后预定的几周内有很长的“假期”,则可能会失败。
  • 尝试将输入参数和输出值添加到您问题中的算法中,这样会更清楚
  • 我更愿意回答有编码问题的问题。我认为解决此问题的最佳方法是使用 Visio Professional 并计划您的想法并查看它是否有效。然后如果您在执行某些部分代码时遇到问题,请向我们询问您的下一个问题。 :)
  • 您可以使用一些向前向后调度的优化来防止amit提到的问题。请参阅此以获得一些灵感;)LI,K.;WILLIS,R.:资源受限调度的迭代调度技术; 1992;欧洲运筹学杂志 56; S.374
  • 感谢大家的回答...仅仅因为一个问题是关于一个明显众所周知的问题并不一定意味着它是学校作业。如果您怀疑我,请查看我的其他问题...

标签: c# algorithm f#


【解决方案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']
    

    【讨论】:

    • 感谢代码示例。至于这是家庭作业,您可以在网站上查看我的其他问题,看看我显然不在学校... :)
    • 你的结果会使 B 连续工作两次。根据问题,这是被禁止的,对吗?
    • 真的很抱歉,我是多任务处理。错误是谓词使用&amp;&amp; 而不是||
    猜你喜欢
    • 2019-05-12
    • 1970-01-01
    • 2014-03-17
    • 1970-01-01
    • 2011-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多