详细介绍匈牙利算法步骤

这篇博客介绍了匈牙利算法的操作步骤,不讨论原理。

作用

解决指派问题。所谓的指派问题就比如:甲乙丙三个人去做ABC三件事情。每个人做每件事情所花的时间可能不一样。每个人只能安排一件事情,问怎样安排才能使三个人所工作的时间之和最小?
扩展成 n 个人 n 件事也可以,但要求是:

  • 事情数和人数一样多
  • 每人只能做一件事
    这样的问题就称作指派问题
    匈牙利算法就是解决这样的问题的。

实例

甲乙丙中第i (i=1,2,3)个人做ABC中第j (j=1,2,3)件事的时间为 Aij。矩阵 A 如下

 2 3 4
 3 4 6
 5 6 1

就是说甲做A事情要2分钟,做B事情要3分钟; 乙做C事情要6分钟,以此类推。问怎样安排才能使甲乙丙三人所用的时间最少?
下面用匈牙利算法来解。

算法目标

让矩阵中出现 n 个满足不同行不同列的 0。 上述问题就是要3个不同行不同列的0.

步骤概括

  1. 每行减去此行最小数
  2. 判断是否达到算法目标,如未达到算法目标,继续下一步。否则结束。
  3. 横纵交替,从行开始。找出所有还没有选中0的行(具体见步骤实例),在此行后面打钩; 把此行中有0的列全打钩。在打钩的列中,如果有零,又在有0的行打钩,如此交替,直到不能再打钩。
  4. 没有打钩的行和打钩的列上划线,会得到发现所有的0已经被划去,如果没有划去,请检查前面的步骤。此时剩下的所有元素中,找到最小值,就记为min吧。
  5. 在第4步画线的行减去min(此时原来的0变成-min),再在画线的列加上min(此时矩阵中没有了负数)。回到第 2 步。

步骤实例

对于之前的矩阵

2 3 4
3 4 6
5 6 1
  1. 每行减去此行最小值,由(1)变成(2),如图:

在这里插入图片描述
2. 检查发现没有达到算法目标,因为(2)中只有两个不同行不同列的0,图中红色的0。没有达到算法目标
3. 找出没有选中0,在后面画勾,如图(3)。
此行的0在第1,在第 1 列画勾,如图(4),发现第 1 列有两个 0,其中第一行的 0 还没有画勾,于是在第 1 行后画勾,如图(5)。此时没有勾可画了,进行下一步。
在这里插入图片描述
4. 在没有打钩的行,即第 3 行,和打钩的列,即第 1 列,划线,会得到发现所有的0已经被划去。然后找出最小值min,此处min = 1。如图(6)
在这里插入图片描述
5. 在第4步画线的行减去min,即在第1、2行减去 1,结果如图(7)。再在画线的列加上min,即在第 1 列加上 1,结果如图(8)。
在这里插入图片描述
6. 判断发现(8)满足算法目标,当然也有图(9)满足算法目标
在这里插入图片描述

最后一公里

如图(8),第1、2、3行的 0 分别在相应行的第 1 、2、3个,所以第 1 个人做第 1 件事,第 2 个人做第 2 件事,第 3 个人做第 3 件事。
图(9)对应的是第 1 个人做第 2 件事,第 2 个人做第 1 件事,第 3 个人做第 3 件事。
带入图(1)计算可以知图(8)和图(9)所用的时间相同,都是(2+4+1 = 7)或 (3+3+1 = 7)分钟。
我们把图(8)和图(9)的结果分别写成

1 2 3 
1 2 3 
1 2 3
2 1 3

总结

要想最快掌握匈牙利算法,就在看完我这篇博客后自己默写一篇。我就是这样做的,现在感觉很好。教别人是一种很好的学习方式,没人教就自己写写博客分享喽!你也可以自己算一个例子试试,其实我已经帮你想好了:对于下面的矩阵,求最少工作量。(希望在你的手机或电脑屏幕上也能看到的矩阵排列得整齐,美感总是很重要的)

5    7  11   5  7
4    8   3   2  2
5    4   6  10  7
10  12  11  10 10
3    7   8   4  5

我得出的结果如下,也未必对,我没有检查:

1 2 3 4 5
4 5 2 3 1

文中若有不足之处,欢迎指正。

猜你喜欢

转载自blog.csdn.net/gengli2017/article/details/84259878
今日推荐