匈牙利算法 - 任意选择

时间:2016-08-08 19:22:28

标签: graph-algorithm hungarian-algorithm

我已经查看了解决分配问题的匈牙利算法的几种解释,其中绝大多数都涵盖了非常简单的案例。

我发现的最明白的解释是YouTube video

我可以对算法进行编码,但我关注的是一个特例。如果您观看视频,相关案例会从31:55到37:42解释,但我会在下面解释。

我首先应该提到我将处理300 x 300矩阵,因此目视检查是不可能的。另外,我需要找到所有最小分配。换句话说,如果有多个赋值产生相同的最小值,我需要全部找到它们。

这是我关注的特殊情况。你可以see this explained in the YouTube video但我会在这里讨论它。我们从这个矩阵开始:

3   1   1   4
4   2   2   5
5   3   4   8
4   2   5   9

当我们减少行和列时,我们得到这个:

0   0   0   0
0   0   0   0
0   0   1   2
0   0   3   4

(让我提一下,我可以直观地看到这个矩阵有4种解决方案,总分为13。)

鉴于上面的简化矩阵,任何行或列都没有唯一的零,因此,根据视频中描述的算法,我可以任意选择任何零元素进行分配,所以我选择(1,1)。

我将用星号标记分配的零,并且我将在行和列中的那些零旁边放置一个“x”,这些行不再可用于考虑。现在我们有了这个:

0*  0x  0x  0x
0x  0   0   0
0x  0   1   2
0x  0   3   4

接下来,我们继续检查行的唯一零。我们在(3,2)处找到一个,所以我们用星号标记它,用" x"标记不可用的零:

0*  0x  0x  0x
0x  0x  0   0
0x  0*  1   2 
0x  0x  3   4

接下来,我们开始在列中查找唯一的零(因为所有行都已耗尽)。我们发现第三列在(2,3)处有一个唯一的零,所以我们标记它:

0*  0x  0x  0x
0x  0x  0*  0x
0x  0*  1   2
0x  0x  3   4

此时,没有更多可用的零,并且第4行未被分配。 (此特定YouTube视频现在使用“滴答程序”,这是确定覆盖所有零所需的最小行数的常用技术。如果您不熟悉此技术,则从14:10开始解释16:00,虽然演示者使用的矩阵与此处显示的不同。)“滴答程序”是这样的:

  1. 勾选所有没有指定零的行(第4行)。
  2. 对于勾选的每一行,勾选该行中包含零的列。
  3. 对于在步骤2中勾选的每个列,勾选已分配零的相应行。
  4. 重复步骤2和3,直到不再可以打勾。
  5. 在所有打勾的列和未勾选的行中绘制线条。
  6. 此时,滴答程序生成4条垂直线,覆盖全零。四条垂直线告诉我们矩阵中的零表示一个或多个解,然而,正如我们所见,第4行是未分配的。尽管有四条垂直线,但第四行仍未分配的事实告诉我们,我们选择了错误的零来进行分配!

    视频的演示者表明这个问题是我们对元素(1,1)的初始(任意)分配的结果。主持人说,“有更复杂的方法可以让我们摆脱这种情况,因为他没有解释这些技术是什么。他暗示存在选择零的“智能”方式,而不是我们用于在(1,1)处选择零的任意选择。

    当我面临进行任意分配时,我可以采取的一种方法(我不确定它是最好的)是使用最少数量的可选任意选项从行或列进行分配。在这个例子中,这意味着我将从第3行或第4行进行任意赋值,其中只有两个任意选择,而不是从第1行或第2行中有四个任意选择。当然,由于我需要所有正确的解决方案,因此无论何时进行任意分配,我都必须迭代所有可用的任意赋值。例如,如果我选择(3,1)作为任意赋值,我也必须稍后赋值(3,2)。

    毕竟,我的问题是,当我面临选择任意选择归零的选择时,最好的方法是什么?这是我在前一段中提到的吗?如何消除所示的死端解决方案?请记住,我仍需要列举所有具有相同最低分数的解决方案。

1 个答案:

答案 0 :(得分:3)

一旦对所有行和列执行了减法步骤,就像你一样,算法中有这一步骤,要求你找到你可以找出的最小行数或列数,以便找不到更多的零留下的单元格(参见Wikipedia article中的第3步)。如果此最小数量的删除行/列等于 n ,那么您已到达矩阵,其中的分配可以在 all 的位置进行由零表示。

第二个矩阵就是这种情况。

一旦你完成了所有可能的减法步骤,就会有这个算法步骤:如果一行或一列只有一个零,那么零表示(最佳)赋值

我认为规则可以概括如下:

  

如果 i 行(或列)最多只有 i 零,那么这些零的 i 代表(最佳)赋值。

i n 时,该规则显而易见(并且完全无益)。

但是对于小 i ,这可能会有所帮助,尽管找到这些行的算法可能很耗时。在示例问题中,我们发现对于 i = 2 ,规则适用于第3行和第4行。规则还意味着我们可以禁止包含零的列中的任何其他分配。这意味着我们可以将矩阵编写为:

-   -   0   0
-   -   0   0
0   0   1   2
0   0   3   4

现在规则可以再次应用于第1行和第2行,每行现在也只有2个零。

我们看到两个只有零的子矩阵(我们应用规则的主题):

0   0
0   0

有两种方法可以进行作业:

x   0
0   x

或:

0   x
x   0

通常,对于具有 i 行和 i 列的子矩阵,有i!解决方案,如果它的所有元素都为零,但如果其中一些元素不是,则更少。

在concreate例子中,有2个!左下方子矩阵的解决方案,2!对于右上方的矩阵,产生了4种可能的解决方案。

结论

虽然上述考虑因素可能听起来很有意思,但我认为搜索此类子矩阵的算法比只按有序方式选择任务的算法更有效,并且一旦发现就会回溯它走错了路。由于您需要所有解决方案,因此从某一行开始是没有意义的。回溯应该确保算法不会浪费时间在没有未来的选择上。