【问题标题】:Hungarian algorithm: I'm having trouble with assigning as many jobs to workers as possible匈牙利算法:我无法为工人分配尽可能多的工作
【发布时间】:2013-03-10 06:31:36
【问题描述】:

我在 C++ 中创建了匈牙利算法的实现。此实现非常适用于许多 种情况。但是,在某些情况下,我的算法根本不起作用,因为我相信(这是真的)我对算法的一个步骤的实现是错误的。

我的实现将数组X 作为输入,运行算法的步骤并产生最终分配。

算法的步骤可以在wiki上找到:Hungarian Algorithm

在第 3 步中,它具有以下成本数组(工人由行表示,工作由列表示)

然后它说

Initially assign as many tasks as possible then do the following 

但是我不明白这个正确的实现是什么。如何分配尽可能多的任务?选择会是随机的吗?如果选择是随机的,我可以选择第一个工人做第一份工作,第二个工人做第四份工作,第四个工人做第二份工作。所以第二个工人被排除在外。然而,在维基百科中,作者采取了不同的方法。第三个工人必须做第一份工作,第二个工人必须做第二份工作,第四个工人必须做第二份工作。所以第一个工人被排除在外。

做这种随机动作的问题如下:

假设当我们运行算法并对输入进行算术运算时,在将尽可能多的任务分配给工作人员之前,我们有以下成本矩阵:

2 2 0 3
6 1 6 0
0 0 6 1
0 3 5 3

如果我随机选择将第三个工作分配给第一个工人,将第四个工作分配给第二个工人,然后将第一个工作分配给第三个工人,我将遗漏第四个工人。但是为了让算法正常工作,我们需要分配as many jobs to workers as possible。这是这里的情况吗?不,因为如果不是将第一份工作分配给第三名工人,而是将第一份工作分配给第四名工人,那么我可以将第二份工作分配给第三名工人,因此该算法不仅会为工人分配尽可能多的工作但它会找到最佳结果。

结论:随机分配并不是一个好办法。

我搜索了一下,找到了以下讲座:

http://www.youtube.com/watch?v=BUGIhEecipE

在本次讲座中,教授提出了一种不同的方法来解决分配尽可能多的任务的问题。 根据他的说法,如果任何行或列恰好有一个零,我们将进行分配。所以从第一行开始你检查第一行是否 只有一个零,如果是这种情况,请进行分配。否则忽略该行并转到第二行,做同样的事情 通过重新扫描表来重复,直到由于分配而覆盖了所有零。

按照这种方法,可以看出前面的情况已经解决了。我们所做的是,我们将第三个工作分配给第一个工人,第四个工作分配给第二个工人,然后我们看到第三个工人可以做两个工作所以我们暂时忽略他,我们将第一个工作分配给第四个工人然后返回以便将第二个工作分配给第三个工人。

我的实现遵循这个逻辑,但同样,它并不能解决所有情况。

我们以下面的例子为例:

0 0 0 0
0 0 0 0
0 0 4 9
0 0 2 3

第一个工人可以做 4 个工作,第二个 4,第三个 2 和第四个 2。所以我的实现没有分配,因为我需要至少一个只能做一个工作的工人才能完成任务然后通过重新扫描表格继续。 那么在这种情况下我该怎么办?随意分配是一件坏事,不幸的是,在那场讲座中没有提出任何建议。 我只能想到以下几点:

对于每个工人都有一个计数器,其值表示可以分配给他的任务数量,那么该行中有多少个零?这就是计数器的值。 然后开始将任意任务分配给计数器最小的工人。所以在这种情况下,每个工人的计数器数组将包含以下值:

4
4
2
2

例如,我会选择第三名工人并任意分配给他第一份工作。新的计数器将是:

3
3
0
1

然后我会选择第四个工人并为他做唯一可用的任务(这是第二份工作)。新的计数器将是:

2
2
0
0

然后我可以选择第一个工人或第二个工人。我会给第一个工人做一个任意的任务,然后给他第三个工作。计数器将是

1
0
0
0

最后我会把第四个任务分配给第一份工作。

所以最后的作业:

0 0 0 *
0 0 * 0
* 0 4 9
0 * 2 3

这似乎是一个不错的方法,但我担心这种方法可能会出现特殊情况。我如何验证这种方法是否适用于所有情况,如果不行,哪种方法可以完全解决我的问题?

提前谢谢你

【问题讨论】:

  • 匈牙利算法?工作人员?没办法……[/自嘲讽刺]
  • 我喜欢你目前的做法——“我相信(而且是真的)”。
  • @H2CO3,我打算发帖“你确定这不是希腊算法吗?”但你应该在这里拥有整个房间;)

标签: c++ c optimization hungarian-algorithm


【解决方案1】:

您当前的方法不起作用

0 2 0
3 0 0
4 0 0

你的方法:“然后开始将任意任务分配给计数器最小的工人。”所有工人都有相同的计数器,所以假设你选择工人 1 并将他分配给任务 3,你只能匹配剩余的工人之一,而使用此矩阵,您显然可以匹配所有三个。

您需要的是这些工人和任务之间的最大二分匹配,如果相关位置有 0,则一对是可匹配的。这种匹配可以通过手动通过增广路径或使用 Hopcroft-Karp 算法更快地找到。

【讨论】:

    猜你喜欢
    • 2018-06-14
    • 2015-06-15
    • 2015-09-02
    • 2013-05-18
    • 2010-11-16
    • 1970-01-01
    • 2011-05-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多