匈牙利算法java实现_匈牙利算法(Hungarian Algorithm)

匈牙利算法是一种在多项式时间内求解任务分配问题的组合优化算法。换句话说就是,在可以接受的时间内去做匹配。

1. 描述问题

给定2个集合A和B,然后将AB中的元素完成一个连线。(这不就是小时候的连线题么-_-)

4609bfa966aeaca250e356c0e97243e4.png

匈牙利算法就是要找到两个集合促成最多的匹配对!最佳媒婆。这里最适合举的例子就是相亲会。集合A代表所有男嘉宾,集合B代表所有女嘉宾。每个男女嘉宾都有自己的心动嘉宾,此为重要前提。通过一个算法,完成最多的牵线。

3967b99c792c9d3d695890a215aaf89e.png

互相有红线的代表互相心动,但不代表最终连线。这里的前提是,Hungarian算法只会匹配互相心动的对象。

最终获得的匹配是:

23450763085cac46434fb4620f13744a.png

上面这篇博客完美解释的Hungarian算法的操作步骤:用递归回溯的方式更改匹配。但没从数学原理上解释。

这里完成最大匹配的逻辑是,先找一个小匹配(至少完成2对牵手的,并且有两对一的关系存在),然后通过M型交错路径的方法扩大匹配。

什么是M型交错路径?

96bd59e00223c1ad15c3bc0c43c81b8d.png

如上图,红色粗线部分为小匹配,构成了一个M型的基本样子,通过M形状延申就可以获得更大的匹配。更新如下,粗线为更新后的匹配:

5d69774225c2a5fd88d8a8127b1a7605.png

与上一步完全不一样,那么这么更新的逻辑是什么呢?答:M型

咱们展开来看,把右下角的点移动到左下角,就可以看得更清楚了:

c7776c85278e2977783eb1c359592b7c.png

匹配一直更新的逻辑是:M字母的阴面和阳面的交替!就是这样,粗线代表连接,细线代表

1eea34d5bb406c93dc369b40a7c8ab25.png

上面这个就是Hungarian算法的精髓了,这个步骤有个专业的名词:M交错路径的增广。

以上。

匈牙利算法是一种用于解决指派问题的优化算法,其主要用途是在给定的两组元素之间建立最优的一对一关系。匈牙利算法的 Matlab 实现如下: ```Matlab function [assignments, cost] = hungarian_algorithm(cost_matrix) m = size(cost_matrix, 1); n = size(cost_matrix, 2); % 第一步:行减去当前行的最小值 for i = 1:m row_min = min(cost_matrix(i, :)); cost_matrix(i, :) = cost_matrix(i, :) - row_min; end % 第二步:列减去当前列的最小值 for i = 1:n column_min = min(cost_matrix(:, i)); cost_matrix(:, i) = cost_matrix(:, i) - column_min; end % 第三步:用最少的线覆盖所有的0 assignments = zeros(m, 1); star_matrix = zeros(m, n); prime_matrix = zeros(m, n); covered_rows = zeros(m, 1); covered_columns = zeros(n, 1); while true [row, column] = find(cost_matrix == 0 & ~covered_rows & ~covered_columns, 1); if isempty(row) break; end star_matrix(row, :) = 1; prime_matrix(row, column) = 1; covered_rows(row) = 1; covered_columns(column) = 1; end % 第四步:寻找未覆盖元素中的最小值 while true [row, column] = find(cost_matrix == 0 & ~covered_rows, 1); if isempty(row) break; end prime_matrix(row, column) = 1; [star_row, ~] = find(star_matrix(row, :) == 1, 1); if isempty(star_row) path = [row, column]; while true [star_row, star_column] = find(star_matrix(:, path(end, 2)) == 1, 1); prime_matrix(star_row, path(end, 2)) = 0; path = [path; star_row, path(end, 2)]; [prime_row, prime_column] = find(prime_matrix(:, path(end, 2)) == 1, 1); path = [path; prime_row, path(end, 2)]; if isempty(star_column) break; end path = [path; star_row, star_column]; end for i = 1:size(path, 1) if mod(i, 2) == 1 star_matrix(path(i, 1), path(i, 2)) = 1; else star_matrix(path(i, 1), path(i, 2)) = 0; end end covered_rows = zeros(m, 1); covered_columns = zeros(n, 1); for i = 1:size(star_matrix, 1) [star_row, ~] = find(star_matrix(i, :) == 1, 1); if ~isempty(star_row) covered_rows(i) = 1; covered_columns(star_row) = 1; end end cost_matrix(cost_matrix == 0 & (covered_rows | ~covered_columns)) = Inf; cost_matrix(cost_matrix == 0 & (~covered_rows | covered_columns)) = 0; else covered_rows(row) = 1; covered_columns(star_row) = 0; end end % 计算最优解和最小代价 assignments = find(star_matrix == 1); cost = sum(cost_matrix(assignments)); end ``` 这是一个实现匈牙利算法的 Matlab 函数。它接受一个代价矩阵作为输入,并返回一个分配结果和最小代价。你可以使用这个函数来解决任何指派问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值