分配作业的递归
Posted
技术标签:
【中文标题】分配作业的递归【英文标题】:Recursion for assigning jobs 【发布时间】:2013-05-20 22:13:36 【问题描述】:这是一个具体的问题,所以我会先快速解释一下背景。我正在开发一种软件,可以将员工分配到当天的特定“工作”。为了让他们从事这项工作,他们必须接受培训,这样系统才能知道每个员工接受过哪些培训,哪些还没有接受过培训。
现在我正在做的事情是这样的:
foreach ($jobs as $job)
foreach($employees as $emp)
if (job doesn't have employee && employee isn't assigned to job && employee has been trained on job)
assign them;
break;
这有点工作,但是有一个问题。请考虑以下简化示例。
有 2 个工作:“结帐”和“客户服务”
有 2 名员工:“Bill”和“Lucy”。 Bill 两种工作都知道,Lucy 只知道 Checkout。
当循环运行时,它会首先寻找工作结帐的人。它将首先查看比尔,看看他是否可以工作,然后分配给他。他们将继续寻找客户服务。它跳过账单,因为他已经被分配,并检查露西,但她不能工作!这会导致不必要的培训。
我可以轻松地对其进行编码,这样如果它遍历所有员工并且找不到任何人,它会像这样通过:
//We didn't find anyone, let's look for a potential swap
foreach($employees as $emp)
if (emp has been trained on job && emp is already assigned something else)
//Find someone else to work their assigned job, so they can work this one
foreach($employees as $emp2)
if ($emp != $emp2 && emp2 can work emp's job && emp2 isn't already assigned anything)
swap the two;
相当简单。但这仅适用于与 2 名员工打交道的交换。如果交换如此复杂以至于需要移动四个人怎么办?理想情况下,我想提出一个递归解决方案,我可以设置一个值 $maxDepth = 5 或其他值。
如果它不能立即找到某人,它会进入深度 2,寻找我上面描述的两人交换。如果仍然不能,它会进入深度 3 寻找三人交换等。
【问题讨论】:
这是所谓的背包问题的变体。 en.wikipedia.org/wiki/Knapsack_problem。 wiki 页面包含伪解决方案,也许可以帮助您。 正如 MaX 所说,这个问题是 NP-Complete... 你的贪心算法会让你陷入困境。您可能需要考虑一个动态编程解决方案,该解决方案将有效地查看所有可能分配的子集,但以一种智能的方式进行记忆。 en.wikipedia.org/wiki/Knapsack_problem#Dynamic_programming 我一定会调查那些资源的,非常感谢。 Swiecki,出于好奇,你说我的算法贪婪是什么意思? 贪心算法是指在每一步都尽可能做到最好的算法,但无法为更好的整体结果做出短期牺牲。示例:您的算法总是将工作分配给第一个空闲员工,但无法知道它不应该选择 Bill 担任工作 1,因为在最佳解决方案中它需要他担任工作 2。 不明白为什么大家都在想背包问题。对我来说似乎是一个分配问题。 en.wikipedia.org/wiki/Assignment_problem。可以使用匈牙利算法en.wikipedia.org/wiki/Hungarian_algorithm 在 O(n^3) 或 O(n^4) 中求解。 (***的解释不是很好,希望你可以通过谷歌搜索找到更好的解释。) 【参考方案1】:具体来说,这是一个Bipartite graph,其中您想要最大匹配数,这可以简化为网络流问题并使用 Ford-Fulkerson 算法解决。这很好解释here。
【讨论】:
这几乎是完美的!我唯一的问题是,您是否听说过一种方法可以做到这一点,因此并非所有边缘都是平等的。 IE。一个边缘比另一个边缘更理想,但如果需要,较小的边缘仍然是一种选择。 我最终使用了基于 Max Flow Min Cost 的 Ford-Fulkerson 算法的修改版本。匈牙利算法也是一个很好的解决方案。谢谢! 感谢您找到解决方案! :D 我不会看到 Ford-Fulkerson 如何处理权重,因为在这种情况下首先会想到匈牙利算法。 这是正确的。我在下面提交的答案不正确,我已将其标记为删除。 已投票,但您需要actually include the information in your answer 而不仅仅是提供链接。这可以防止链接腐烂。以上是关于分配作业的递归的主要内容,如果未能解决你的问题,请参考以下文章