分派问题(匈牙利算法)与MATLAB实现

一、分配问题

问题描述:有n项不同的任务,需要n个人分别完成其中的一项,由于各人去完成不同的任务所花费的时间(或费用)不同。于是产生了一个问题,应指派哪个人去完成哪项任务,使完成n项任务的所需时间最少。

二、匈牙利算法介绍

匈牙利算法是一种在多项式时间内求解任务分配问题的组合优化算法,并推动了后来的原始对偶方法。美国数学家哈罗德·库恩于1955年提出该算法。此算法之所以被称作匈牙利算法,是因为算法很大一部分是基于以前匈牙利数学家Dénes Kőnig和Jenő Egerváry的工作之上创建起来的。

其基本的理论基础是针对cost矩阵,将cost矩阵的一列或一行加上或减去一个数,求解最优任务的结果不变。
算法步骤:
第一步: 变换指派问题的系数矩阵,使 各行各列中都出现0元素
第二步:进行试分配,以寻求最优解。如果得到最优解,运算结束,否则转到第三步。
第三步:作最少的直线覆盖所有0元素。
第四步:变换矩阵(bi)以增加0元素,转到第二步。

三、匈牙利算法实例分析

利用匈牙利法解决如下任务分配问题。
图为cost列表和cost矩阵
图为cost列表和cost矩阵。
第一步:将每行减去当前行的最小值(不一定是最小值,减去某一个值是为了让当前行中出现0元素,第二步的列同理)
每行减去当前行的最小值
第二步:将每一列的值减去当前列的最小值
每一列的值减去当前列的最小值
第三步:利用最少的水平线或者垂直线覆盖所有的0
在这里插入图片描述
第四步:如果水平线和垂直线的总数小于4(矩阵的维度),则计算没有被覆盖的最小值,将没有被覆盖的每行减去最小值,被覆盖的每列加上最小值,然后跳转到步骤三。如果水平线和垂直线的总数等于4(矩阵的维度),则算法结束,得到分配结果。
在这里插入图片描述
第三步:利用最少的水平线或者垂直线覆盖所有的0
在这里插入图片描述
第四步:水平线和垂直线的总数等于4,算法结束,得到如下的分配结果
在这里插入图片描述
左边矩阵0元素的选取原则应该是一行和一列中只选取一个元素(即一个人只能工作一个任务),等价与右边的最优分配。

四、MATLAB实现

Hungary.m

function res=Hungary(N)
%输入的矩阵应N*N[a,~]=size(N);
%第一步每一行减去当前行最小值
for ii = 1:a
    N(ii,:)= N(ii,:)-min( N(ii,:));
end
%第二步每一列减去当前列最小值
for ii = 1:a
    N(:,ii)=  N(:,ii)-min( N(:,ii));
end
num=0;
while num~=a
    [num,N_min,del_hang,del_lie]=line_count(N);
    if num ~=a
        for ii=1:a
            if del_hang(ii)~=ii
                N(ii,:) =  N(ii,:)-N_min;
            end
            if del_lie(ii)==ii
            N(:,ii) =  N(:,ii)+N_min;
            end
        end
    else
        res=N;
    end
end

line_count.m

function [num,M_min,del_hang,del_lie]=line_count(M)
[a,~]=size(M);
num=0;
h=0;
del_hang=zeros(a,1);
del_lie=zeros(a,1);
for ii=1:a
    del=ii-h;
    [~,b]=size(find(M(del,:)==0));
    if   b>= 2
        M(del,:)=[];
        h=h+1;
        del_hang(ii)=ii;    %得到被覆盖的行数
        num=num+1;
    end
end
l=0;
for ii=1:a
    del=ii-l;
    [b,~]=size(find(M(:,del)==0));
    if  b >=1
        M(:,del)=[];
        l=l+1;
        del_lie(ii)=ii;    %得到被覆盖的列数
        num=num+1;
    end
end
M_min=min(min(M));

linear_assignment.m

function [place,res]=linear_assignment(M,N)
%N是n维矩阵,N是经过Hungary处理的
%M是未处理前的
[a,~]=size(N);
x=0;
place=zeros(1,a);
res=zeros(1,a);
judge=zeros(1,a);
while find(N==0)
    for ii=1:a
    judge(ii)=length(find(N(ii,:)==0));
    end
    judge(find(judge==0))=[];
    if min(judge)==1
     for ii=1:a
        if length(find(N(ii,:)==0))==1     %先选出行中只有10
            x=x+1;
            place(x)=ii+(find(N(ii,:)==0)-1)*a; %得到矩阵中的位置
            h=find(N(ii,:)==0);
            N(ii,:)=1./zeros(1,a);
            N(:,h)=1./zeros(a,1);
        end
     end
    end
    
    for ii=1:a
    judge(ii)=length(find(N(ii,:)==0));
    end
    judge(find(judge==0))=[];
    
    if min(judge)==2
       x=x+1;
    q=find(N==0);
    place(x)=q(1);
    N(mod(q(1),a),:)=1./zeros(1,a);
    N(:,fix(q(1)/a)+1)=1./zeros(a,1);  
    end
end
[place,~]=sort(place);
for ii=1:length(place)
    res(ii)=M(place(ii));
end
 
 

运行时代码:

A=[6 7 11 2;
    4 5 9 8;
    3 1 10 4;
    5 9 8 2];
B=Hungary(A);
[~,b]=linear_assignment(A,B)

得到的结果:
b =

 4     1     8     2

与前面分析的结果一致。

  • 45
    点赞
  • 369
    收藏
    觉得还不错? 一键收藏
  • 33
    评论
Matlab实现匈牙利算法的步骤如下: 1. 首先,使用行处理和列处理函数(rc)将待处理的矩阵进行处理。这一步是算法的第一步,通过减去当前行的最小值和当前列的最小值来对矩阵进行变换。 2. 接下来,通过划线来进一步处理矩阵匈牙利算法中,覆盖所有0的线的数量等于矩阵的维度,这意味着处理已经完成。 3. 如果处理还未完成,则继续进行试分配,以寻求最优解。如果得到最优解,则算法结束。如果没有得到最优解,则转到下一步。 4. 下一步是作最少的直线覆盖所有0元素。 5. 最后一步是变换矩阵,以增加0元素,并返回到第二步进行下一次迭代。 通过以上步骤,可以在Matlab实现匈牙利算法。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [分派问题匈牙利算法)与MATLAB实现](https://blog.csdn.net/qq_36980029/article/details/96626332)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [匈牙利算法MATLAB实现](https://blog.csdn.net/kuihan8061/article/details/101313221)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 33
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值