匈牙利算法解决指派问题
- 指派问题背景介绍
- 算法原理
- 算法实现
指派问题背景介绍
在实践中经常会遇到这样一种问题:有n项不同的工作或任务,需要n个人去完成,要求每人只完成一项工作。由于每人的知识、能力、经验等不同,故各人完成不同任务所需要的时间不同。问应指派何人完成何项工作,使完成n项工作总耗时最少
这就是所谓的指派问题,指派问题也是整数规划问题
算法原理
定理1
设指派问题的效率矩阵为 ,若将该矩阵的某一行或列的各元素都减去同一个常数t,得到新的效率矩阵 ,则以C’为效率矩阵的新指派问题与原指派问题的最优解相同,但其最优值比原最优值减少t
定理2
若将指派问题的效率矩阵每一行及每一列分别减去各行及各列的最小元素,则得到的新指派问题与原指派问题有相同的最优解
- 将效率矩阵的每一行减去各行最小元素,所得矩阵的每一列再减去当前列中最小元素,最后的新效率矩阵C’中必然会出现一些零元素
- 元素 =0表示第i个人去干第j项工作效率最好,或表示第j项工作由第i个人来干效率最高
定理3
效率矩阵C中独立零元素的最多个数等于能覆盖所有零元素的最小直线数
定义1
在效率矩阵C中,有一组处在不同行不同列的零元素,称为独立零元素组,此时其中每个元素称为独立零元素
算法实现
Step 1
变化效率矩阵,将各行各列都减去当前各行各列最小元素
function [P_cond,stepnum] = step1(M)
size = length(M);
for i = 1:size
row_min = min(M(i,:));
M(i,:) = M(i,:)-row_min;
end
stepnum = 2;
Step 2
用圈零法求出新矩阵C1中独立零元素
- 进行行检验
对C1进行逐行检查,每行只有一个未标记的零元素时,用O记号将该元素圈起,然后将被圈起的零元素所在列的其他未标记的零元素用记号×划去
重复行检验,直到每一行都没有未被标记的零元素或至少有两个未被标记的零元素为止 - 进行列检验,与进行行检验类似
function [r_cov,c_cov,C,stepnum] = step2(M)
% Define variables
size = length(M);
r_cov = zeros(size,1); % 显示是否覆盖行的向量
c_cov = zeros(size,1); % 显示是否覆盖列的向量
C = zeros(size); %显示一个位置是O还是×
for i = 1:size
for j = 1:size
if M(i,j) == 0 && r_cov(i) ==