https://en.wikipedia.org/wiki/Hungarian_algorithm
http://www.hungarianalgorithm.com/index.php
匈牙利算法是解決分配問題(assignment problem)的算法,使用第二個網址中的例子講解:
問題描述:我們公司有三項任務,要外包給三個工人,每個工人有不同的收費標准,比如任務1,復現mask rcnn,任務2,復現deeplabv3,任務3,復現resnet。三個煉丹師(a,b,c)分別收費如下表:
任務1 | 任務2 | 任務3 | |
---|---|---|---|
a | 78 | 87 | 38 |
b | 37 | 71 | 5 |
c | 50 | 97 | 66 |
老板又比較摳門,要求用最少的錢完成這三項任務。
我們嘗試分配任務,力求每個人的花費都最低
匈牙利算法:
步驟1,subtract the row minimum from each row
對每個人減去最小花費值,
任務1 | 任務2 | 任務3 | ||
---|---|---|---|---|
a | 40 | 49 | 0 | (-38) |
b | 32 | 66 | 0 | (-5) |
c | 0 | 47 | 16 | (-50) |
也就是給a分配任務3,給b分配任務3,給c分配任務1,這時候顯然是有問題的,任務三分配了兩次
step 2: subtract the column minimum from each column
任務1 | 任務2 | 任務3 | |
---|---|---|---|
a | 40 | 2 | 0 |
b | 32 | 19 | 0 |
c | 0 | 0 | 16 |
(-47) |
step3: Cover all zeros with a minimum number of lines
發現只需要用最后一列和最后一行就可以將所有的0cover,說明任務和工人不能完全匹配
step4: Create additional zeros
在uncovered 數列中(a,b兩行的前兩列),減去他們的最小值,並將此值加到被cover兩次的地方(第三部中第一列和最后一行的交叉處)
任務1 | 任務2 | 任務3 | |
---|---|---|---|
a | 38 | 0 | 0 |
b | 30 | 17 | 0 |
c | 0 | 0 | 18 |
重復步驟3、發現此時需要至少3行或者3列才能將所有0 cover
此時的最優分配是b任務3,a任務2,c任務1,87+5+50=142
一些實現方式:
c++
http://software.clapper.org/munkres/
python
https://github.com/xtof-durr/makeSimple/blob/master/Munkres/kuhnMunkres.py