我在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
在这个讲座中,教授为分配尽可能多的任务的问题提出了一种不同的方法。 根据他的说法,如果任何行或列只有一个零,我们将进行一项任务。所以从第一行开始,检查是否第一行 只有一个零,如果是这样,做一个任务。否则忽略该行并转到第二行,执行相同的操作 通过重新扫描表重复扫描,直到由于分配而覆盖所有零。
通过遵循这种方法,可以看出先前的案例已经解决。我们做的是,我们将第三个工作分配给第一个工人,第四个工作分配给第二个工人,然后我们看到第三个工人可以从事2个工作因此我们暂时忽略他,我们将第一个工作分配到第四个工作工人然后返回,以便将第二个工作分配给第三个工人。
我的实现遵循这个逻辑,但是,它并没有解决所有情况。
让我们举例说明以下情况:
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
这似乎是一种很好的方法,但是我担心可能会出现这种方法不起作用的特殊情况。如何验证这种方法是否适用于所有情况,如果不适用,哪种方法可以完全解决我的问题?
提前谢谢
答案 0 :(得分:3)
您当前的方法不工作。
0 2 0
3 0 0
4 0 0
你的方法:“然后开始向具有最小计数器的工人分配任意任务。”所有工人都有相同的计数器,所以说你选择工人1并将他分配给任务3,你只能匹配剩下的工人之一,使用这个矩阵,你显然可以匹配这三个。
您需要的是这些工作人员和任务之间的最大二分匹配,如果相关位置中存在0,则匹配对是匹配的。通过使用Hopcroft-Karp算法手动遍历扩充路径或更快速地找到这种匹配。