【发布时间】: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) 中求解。 (维基百科的解释不是很好,希望你可以通过谷歌搜索找到更好的解释。)
标签: php cakephp loops recursion logic