分配(指派)问题

本文详细介绍了匈牙利算法解决分配问题的过程,包括行归约、列归约、指派任务的具体步骤,以及处理特殊情况的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是分配问题:

分配问题也称指派问题,是一种特殊的整数规划问题,分配问题的要求一般是这样的:

n个人分配n项任务,一个人只能分配一项任务,一项任务只能分配给一个人,将一项任务分配给一个人是需要支付报酬,如何分配任务,保证支付的报酬总数最小

简单的说:就是n*n矩阵中,选取n个元素,每行每列各有一个元素,使得和最小。

匈牙利算法

1、理论基础:

若从指派问题的系数矩阵的某行(列)各元素中分别减去或者加上常数k,其最优任务分解问题不变。

2. 匈牙利算法的流程图

Image

3.计算步骤

例如:有A、B、C、D四项任务,需要分配给甲乙丙丁四个人来完成。他们完成任务所需要支付的酬劳如下表所示,问,如何分配任务,可使总费用最少?

Image

得到的支付矩阵是:

                 Image

Step 1:   行归约

找出每行最小元素,分别从每行中减去这个最小元素;(能够使每必出现“0”

矩阵变换如下:

             Image

Step 2 :   列归约

找出每列最小元素,分别从每列中减去这个最小元素 ; (能够使每必出现“0”

             Image

Step 3 :   指派任务

①   确定独立零元素

   从第一行(列)开始,若该行(列)中只有一个零元素,对该零元素标1,表示这个任务就指派给某人做。

   每标一个1,同时将该零元素同列的其他零元素标为2,表示此任务已不能由其他人来做。(此处标1、2的操作与课本画圈、划去操作同理)

如此反复进行,直到系数矩阵中所有的零元素都已经被标为1或者2为止。我们得到的矩阵如下:

                  Image

此时,只需将0(1)所在位置记为1,其余位置记为0,则获得了该问题的最优解。

最优解为:

                 Image

即:A任务交给丙负责,B任务交给丁负责,C任务交给甲负责,D任务交给乙负责。

此时总报酬为:1+5+2+3 = 11;

其他情况

① 出现零元素的闭合回路   ②标记成1的元素个数小于n

i.出现零元素闭合回路(有多于两行或两列存在两个以上的零元素。)

对于矩阵:

                 Image

我们所有变化后,得到矩阵:

           Image

图的第一行的一二列零元素和第四行的一二列零元素构成回路        (第一行(列)和最后一行(列)看做连通的)

这里我们的处理方法是:

 先对cost方阵做一个备份(因为会出现多解),然后我们可以顺着回路的走向,对间隔的零元素标记成1,然后对标记成1的零元素所有的行列划一条直线,把这两条直线的其他零元素标记成2,得到一种结果后,再求出多解。

这里我们采用间隔标记法,得到矩阵:

         Image

最优解为:

                      Image

最小酬劳为:1+2+2+2=7

ii.   矩阵中所有标记成1的零元素小于n

例如矩阵:

                     Image

经过所有变换后得到矩阵:

                Image

被标为1的0总共有3个,小于4

因此,我们需要对其进行【画盖0线】的操作。(即画出可以覆盖最多0元素的直线)

(1)画盖0线:利用最少的水平线和垂直线覆盖所有的零。

具体操作如下: 

① 对没有标记为1的零元素所在的行打√;

②在已打“√”的行中,对标记为2的零元素所在列打√

③ 在已打“√”的列中,对标记为1的零元素所在行打“√”

④重复②和③,直到再不能找到可以打√的行或列为止。

⑤对没有打“√”的行画一横线,对打“√”的列画一垂线,这样就得到了覆盖所有零元素的最少直线数目的直线集合。

对矩阵进行操作:

① 打勾

               Image

②  划线 

                Image

(2)继续变换系数矩阵

①在未被覆盖的元素中找出一个最小元素。

②对未被覆盖的元素所在行中各元素都减去这一最小元素。这时已被覆盖的元素中会出现负元素。

③对负元素所在的列中各元素加上这一最小元素。

对上述矩阵:20为未被覆盖元素中最小的元素。变换矩阵,并寻找得:

               Image

Step4  

我们发现,在经过一次变换后,独立零元素的个数仍然少于4.此时返回第三步,反复进行,直到矩阵中每一行都有一个被标记为1的元素为止。

例如在上述矩阵中:

矩阵中独立零元素仍然小于n。对矩阵执行打勾、划线等操作,得出未被覆盖区最小元素为5,进行系数变换之后得到矩阵:

                      Image

我们发现得到的矩阵每行列有多个零元素(零元素的闭合回路),再运用上述方法可以得到矩阵:

          Image

最优解为:

            Image

最小酬劳为:15+65+25+50=155

### 匈牙利分配算法简介 匈牙利分配算法是一种用于解决指派问题的有效方法,特别适用于成本矩阵的最小化问题。该算法能够在多项式时间内找到最优解。 ### MATLAB 中的实现方式 在MATLAB中实现匈牙利分配算法可以通过调用内置函数`matchpairs`来完成[^1]。此函数能够有效地求解二分图的最大匹配问题,并返回最佳配对方案及其对应的总代价。 对于自定义实现的情况,则需按照如下逻辑构建程序: #### 自定义实现的关键步骤说明 - 构建初始的成本矩阵; - 对每一行和列减去其内部最小值以简化计算过程; - 尝试通过最少数量直线覆盖所有零元素; - 计算未被划线经过的位置上的最小数并调整剩余项直至得到独立0构成完全匹配路径为止; 下面给出一段简单的示例代码展示如何手动编写匈牙利法的核心部分: ```matlab function assignment = hungarianAlgorithm(costMatrix) % 输入参数 costMatrix 是一个 n×n 的成本矩阵 [row, col] = size(costMatrix); % 步骤一:每行减去本行最小值 minRowValues = min(costMatrix,[],2); reducedCostMatrix = bsxfun(@minus,costMatrix,minRowValues); % 步骤二:每列再减去当前各列内的最小值 minColValues = min(reducedCostMatrix,[],1); finalReducedCostMatrix = bsxfun(@minus,reducedCostMatrix,minColValues); % 接下来的步骤涉及复杂的标记操作与迭代优化... end ``` 这段代码仅展示了前两步的操作,在实际应用时还需要继续完善后续流程才能形成完整的匈牙利算法解决方案。 为了更方便地使用,推荐直接采用MATLAB自带工具箱提供的功能来进行此类运算。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值