运筹学04-整数规划-匈牙利解法

合集下载

运筹学匈牙利法

运筹学匈牙利法

运筹学匈牙利法运筹学匈牙利法(Hungarian Algorithm),也叫匈牙利算法,是解决二部图最大(小)权完美匹配(也称作二分图最大权匹配、二分图最小点覆盖)问题的经典算法,是由匈牙利数学家Kuhn和Harold W. Kuhn发明的,属于贪心算法的一种。

问题描述在一个二分图中,每个节点分别属于两个特定集合。

找到一种匹配,使得所有内部的节点对都有连边,并且找到一种匹配方案,使得该方案的边权和最大。

应用场景匈牙利算法的应用场景较为广泛,比如在生产调度、货车调度、学生对导师的指定、电影的推荐等领域内,都有广泛的应用。

算法流程匈牙利算法的伪代码描述如下:进行循环ɑ、选择一点未匹配的点a作为起点,它在二分图的左边β、找出a所有未匹配的点作为下一层节点ɣ、对下一层的每个节点,如果它在右边未匹配,直接匹配ɛ、如果遇到一个已经匹配的节点,进入下一圈,考虑和它匹配的情况δ、对已经匹配的点,将它已经匹配的点拿出来,作为下一层节点,标记这个点作为已被搜索过ε、将这个点作为当前层的虚拟点,没人配它,看能否为它找到和它匹配的点ζ、如果能匹配到它的伴侣,令它们成对被匹配最后输出最大权匹配。

算法优缺点优点:相比于暴力求解二分图最大权匹配来说,匈牙利算法具有优秀的解决效率和高效的时间复杂度,可以在多项式时间(O(n^3))内解决二分图最大权匹配问题。

缺点:当二分图较大时,匈牙利算法还是有很大的计算复杂度,复杂度不佳,算法有效性差。

此时就需要改进算法或者使用其他算法。

总结匈牙利算法是一个常见的解决二分图最大权匹配问题的算法,由于其简洁、易用、效率优秀等特性,广泛应用于学术和实际问题中。

匈牙利算法虽然在处理较大规模问题时效率不佳,但仍然是一种值得掌握的经典算法。

整数规划问题的求解

整数规划问题的求解
max Z 4 x1 3 x 2 1.2 x1 0.8 x 2 10 2 x1 2.5 x 2 25 LP 21 : x1 4,x 2 6 x1 , x 2 0
C o 3 4
x1
分支定界法
x2
A
Page 16
由 于Z 21 Z 1, 选 择 LP 21进 行 分 枝 , 增 加 约 束 x1 4及x1 5, 得 线 性 规 划 LP 211 及LP 212 :
10
A
x2 7不可行
max Z 4 x1 3 x 2 1.2 x1 0.8 x 2 10 2 x1 2.5 x 2 25 LP 22 : x1 4,x 2 7 x1 , x 2 0
B 6 LP1
LP21
LP21:X=(4.33,6),Z21=35.33
整数规划问题的求解
整数规划问题的求解方法: 分支定界法和割平面法
Page 1
匈牙利法(指派问题)
分支定界法
分支定界法的解题步骤:
Page 2
1)求整数规划的松弛问题最优解; 若松弛问题的最优解满足整数要求,得到整数规划的最优解,否则转下 一步; 2)分支与定界: 任意选一个非整数解的变量xi,在松弛问题中加上约束: xi≤[xi] 和 xi≥[xi]+1 组成两个新的松弛问题,称为分枝。新的松弛问题具有特征:当原问题 是求最大值时,目标值是分枝问题的上界;当原问题是求最小值时,目 标值是分枝问题的下界。 检查所有分枝的解及目标函数值,若某分枝的解是整数并且目标函数 值大于(max)等于其它分枝的目标值,则将其它分枝剪去不再计算,若 还存在非整数解并且目标值大于(max)整数解的目标值,需要继续分枝, 再检查,直到得到最优解。

运筹学--第四章 整数规划与分配问题

运筹学--第四章 整数规划与分配问题

一、整数线性规划问题的提出
引例:生产组织计划问题与选址问题 例4-1(生产组织计划问题)某工厂在一个计划期 内拟生产甲、乙两种大型设备。除了A、B两种部件 需要外部供应且供应受到严格限制之外,该厂有充 分的能力来加工制造这两种设备所需的其余零件, 并且所需原材料和能源也可满足供应。每种设备所 用部件数量和部件的供应限额以及设备的利润由表 3-1-1给出。问该厂在本计划期内如何安排甲、乙 设备的生产数量,才能获取最大利润?
例4-3某人有一背包可以装10公斤重、0.025m3的物
品。他准备用来装甲、乙两种物品,每件物品的重 量、体积和价值如表4-3-1所示。问两种物品各装 多少件,所装物品的总价值最大?
表4-3-1 物品 甲 乙 重量 (公斤/每件) 1.2 0.8 体积 (m3/每件) 0.002 0.0025 价值 (元/每件) 4 3
应寻找仅检查可行的整数组合的一部分,就能定出 分支定界法可用于解纯整数或混合整数线性规划问
最优的整数解的方法。分支定界解法就是其中之一。
题。
–20世纪60年代初由Land Doig和Dakin等提出,是 解整数线性规划的重要方法之一。
–由于这方法灵活且便于用计算机求解,所以现在
它已是解整数规划的重要方法。
了。 但这常常是不行的,因为化整后不见得是可行解; 或虽是可行解,但不一定是最优解。 因此,对求最优整数解的问题,有必要另行研究。
例4-4 说明整数规划问题的求解不能直接在单纯形
法最优解的基础上四舍五入 求下述整数规划问题的最优解(P105)
max z 3x1 2 x2 2 x1 3x2 14 s.t. x1 0.5 x2 4.5 x , x 0, 且均取整数值 1 2

《管理运筹学》分配问题与匈牙利算法

《管理运筹学》分配问题与匈牙利算法

2019/9/10
第 12页
第4章 整数规划与分配问题
4 5 4 ◎ √
◎ 1 Ø 4
2 ◎ 4 3
3
7
1
Ø



3 4 3 ◎
◎ 1 Ø 5
2 ◎ 4 4
2
6
0
Ø

3 4
◎ 1 2 ◎ 2 6
3 ◎
Ø 5
4 4

Ø

得到4个独立零元素, 所以 最优解矩阵为:

7
8
11
9

-7
运筹学
0 13 11 2
6 0 10 11
0 5 7 4
0 1
4
2

2019/9/10
第 6页
第4章 整数规划与分配问题
运筹学
0 13 11 2
6 0 10 11
0 5 7 4
0
1
4
2

-0 -0 -4 -2
0 13 7 0 6 0 6 9 0 5 3 2 0 1 0 0
2019/9/10
第 11页
第4章 整数规划与分配问题
运筹学
第三步,作最少的直线覆盖所有0元素:
4 5 4 ◎ √
◎ 1 Ø 4
2 ◎ 4 3
3
7
1
Ø



独立零元素的个数m等于最少直线数l,即l=m=3<n=4;
第四步,变换矩阵(bij)以增加0元素:没有被直线覆盖的所有元素中的最小元素为1,然后 打√各行都减去1;打√各列都加上1,得如下矩阵,并转第二步进行试指派:
第4章 整数规划与分配问题

运筹学基础及应用第4章-整数规划与分配问题

运筹学基础及应用第4章-整数规划与分配问题

整数规划的特点及应用
解:对每个投资项目都有被选择和不被选择两种可能,因此 分别用0和1表示,令xj表示第j个项目的决策选择,记为:
j投 资 1 对 项 目 xj ( j 1,2,..., n) j不 投 资 0 对 项 目
投资问题可以表示为:
max z
c
j 1
n
j
xj
n a j x j B j 1 x2 x1 s .t x 3 x4 1 x5 x6 x7 2 ) x j 0或者1 (j 1, 2, L n
B1 B2 B3 B4 年生产能力
A1
A2 A3 A4 年需求量
2
8 7 4 350
9
3 6 5 400
3
5 1 2 300
4
7 2 5 150
400
600 200 200
工厂A3或A4开工后,每年的生产费用估计分别为1200万或1500万元。 现要决定应该建设工厂A3还是A4,才能使今后每年的总费用最少。
0-1型整数线性规划:决策变量只能取值0或1的整数线性 规划。
整数规划的特点及应用
整数规划的典型例子
例4.1 工厂A1和A2生产某种物资。由于该种物资供不应求,故需要 再建一家工厂。相应的建厂方案有A3和A4两个。这种物资的需求地 有B1,B2,B3,B4四个。各工厂年生产能力、各地年需求量、各厂至各 需求地的单位物资运费cij,见下表:
例4.3 设整数规划问题如下
max Z x1 x 2 14x1 9 x 2 51 6 x1 3 x 2 1 x , x 0且 为 整 数 1 2
首先不考虑整数约束,得到线性规划问题(一般称为松弛问 题)。

运筹学指派问题的匈牙利法

运筹学指派问题的匈牙利法

运筹学课程设计指派问题的匈牙利法专业:姓名:学号:1.算法思想:匈牙利算法的基本思想是修改效益矩阵的行或列,使得每一行或列中至少有一个为零的元素,经过修正后,直至在不同行、不同列中至少有一个零元素,从而得到与这些零元素相对应的一个完全分配方案。

当它用于效益矩阵时,这个完全分配方案就是一个最优分配,它使总的效益为最小。

这种方法总是在有限步內收敛于一个最优解。

该方法的理论基础是:在效益矩阵的任何行或列中,加上或减去一个常数后不会改变最优分配。

2.算法流程或步骤:1.将原始效益矩阵C的每行、每列各元素都依次减去该行、该列的最小元素,使每行、每列都至少出现一个0元素,以构成等价的效益矩阵C’。

2.圈0元素。

在C’中未被直线通过的含0元素最少的行(或列)中圈出一个0元素,通过这个0元素作一条竖(或横)线。

重复此步,若这样能圈出不同行不同列的n个0元素,转第四步,否则转第三步。

3.调整效益矩阵。

在C’中未被直线穿过的数集D中,找出最小的数d,D中所有数都减去d,C’中两条直线相交处的数都加的d。

去掉直线,组成新的等价效益矩阵仍叫C’,返回第二步。

X=0,这就是一种最优分配。

最低总4.令被圈0元素对应位置的X ij=1,其余ij耗费是C中使X=1的各位置上各元素的和。

ij算法流程图:3.算法源程序:#include<iostream.h>typedef struct matrix{float cost[101][101];int zeroelem[101][101];float costforout[101][101];int matrixsize;int personnumber;int jobnumber;}matrix;matrix sb;int result[501][2];void twozero(matrix &sb);void judge(matrix &sb,int result[501][2]);void refresh(matrix &sb);void circlezero(matrix &sb);matrix input();void output(int result[501][2],matrix sb);void zeroout(matrix &sb);matrix input(){matrix sb;int m;int pnumber,jnumber;int i,j;float k;char w;cout<<"指派问题的匈牙利解法:"<<endl;cout<<"求最大值,请输入1;求最小值,请输入0:"<<endl;cin>>m;while(m!=1&&m!=0){cout<<"请输入1或0:"<<endl;cin>>m;}cout<<"请输入人数(人数介于1和100之间):"<<endl;cin>>pnumber;while(pnumber<1||pnumber>100){cout<<"请输入合法数据:"<<endl;cin>>pnumber;}cout<<"请输入工作数(介于1和100之间):"<<endl;cin>>jnumber;while(jnumber<1||jnumber>100){cout<<"请输入合法数据:"<<endl;cin>>jnumber;}cout<<"请输入"<<pnumber<<"行"<<jnumber<<"列的矩阵,同一行内以空格间隔,不同行间以回车分隔,以$结束输入:\n";for(i=1;i<=pnumber;i++)for(j=1;j<=jnumber;j++){cin>>sb.cost[i][j];sb.costforout[i][j]=sb.cost[i][j];}cin>>w;if(jnumber>pnumber)for(i=pnumber+1;i<=jnumber;i++)for(j=1;j<=jnumber;j++){sb.cost[i][j]=0;sb.costforout[i][j]=0;}else{if(pnumber>jnumber)for(i=1;i<=pnumber;i++)for(j=jnumber+1;j<=pnumber;j++){sb.cost[i][j]=0;sb.costforout[i][j]=0;}}sb.matrixsize=pnumber;if(pnumber<jnumber)sb.matrixsize=jnumber;sb.personnumber=pnumber;sb.jobnumber=jnumber;if(m==1){k=0;for(i=1;i<=sb.matrixsize;i++)for(j=1;j<=sb.matrixsize;j++)if(sb.cost[i][j]>k)k=sb.cost[i][j];for(i=1;i<=sb.matrixsize;i++)for(j=1;j<=sb.matrixsize;j++)sb.cost[i][j]=k-sb.cost[i][j];}return sb;}void circlezero(matrix &sb){int i,j;float k;int p;for(i=0;i<=sb.matrixsize;i++)sb.cost[i][0]=0;for(j=1;j<=sb.matrixsize;j++)sb.cost[0][j]=0;for(i=1;i<=sb.matrixsize;i++)for(j=1;j<=sb.matrixsize;j++)if(sb.cost[i][j]==0){sb.cost[i][0]++;sb.cost[0][j]++;sb.cost[0][0]++;}for(i=0;i<=sb.matrixsize;i++)for(j=0;j<=sb.matrixsize;j++)sb.zeroelem[i][j]=0;k=sb.cost[0][0]+1;while(sb.cost[0][0]<k){k=sb.cost[0][0];for(i=1;i<=sb.matrixsize;i++){if(sb.cost[i][0]==1){for(j=1;j<=sb.matrixsize;j++)if(sb.cost[i][j]==0&&sb.zeroelem[i][j]==0)break;sb.zeroelem[i][j]=1;sb.cost[i][0]--;sb.cost[0][j]--;sb.cost[0][0]--;if(sb.cost[0][j]>0)for(p=1;p<=sb.matrixsize;p++)if(sb.cost[p][j]==0&&sb.zeroelem[p][j]==0){sb.zeroelem[p][j]=2;sb.cost[p][0]--;sb.cost[0][j]--;sb.cost[0][0]--;}}}for(j=1;j<=sb.matrixsize;j++){if(sb.cost[0][j]==1){for(i=1;i<=sb.matrixsize;i++)if(sb.cost[i][j]==0&&sb.zeroelem[i][j]==0)break;sb.zeroelem[i][j]=1;sb.cost[i][0]--;sb.cost[0][j]--;sb.cost[0][0]--;if(sb.cost[i][0]>0)for(p=1;p<=sb.matrixsize;p++)if(sb.cost[i][p]==0&&sb.zeroelem[i][p]==0){sb.zeroelem[i][p]=2;sb.cost[i][0]--;sb.cost[0][p]--;sb.cost[0][0]--;}}}}if(sb.cost[0][0]>0)twozero(sb);elsejudge(sb,result);}void twozero(matrix &sb){int i,j;int p,q;int m,n;float k;matrix st;for(i=1;i<=sb.matrixsize;i++)if(sb.cost[i][0]>0)break;if(i<=sb.matrixsize){for(j=1;j<=sb.matrixsize;j++){st=sb;if(sb.cost[i][j]==0&&sb.zeroelem[i][j]==0){sb.zeroelem[i][j]=1;sb.cost[i][0]--;sb.cost[0][j]--;sb.cost[0][0]--;for(q=1;q<=sb.matrixsize;q++)if(sb.cost[i][q]==0&&sb.zeroelem[i][q]==0){sb.zeroelem[i][q]=2;sb.cost[i][0]--;sb.cost[0][q]--;sb.cost[0][0]--;}for(p=1;p<=sb.matrixsize;p++)if(sb.cost[p][j]==0&&sb.zeroelem[p][j]==0){sb.zeroelem[p][j]=2;sb.cost[p][0]--;sb.cost[0][j]--;sb.cost[0][0]--;}k=sb.cost[0][0]+1;while(sb.cost[0][0]<k){k=sb.cost[0][0];for(p=i+1;p<=sb.matrixsize;p++){if(sb.cost[p][0]==1){for(q=1;q<=sb.matrixsize;q++)if(sb.cost[p][q]==0&&sb.zeroelem[p][q]==0)break;sb.zeroelem[p][q]=1;sb.cost[p][0]--;sb.cost[0][q]--;sb.cost[0][0]--;for(m=1;m<=sb.matrixsize;m++)if(sb.cost[m][q]=0&&sb.zeroelem[m][q]==0){sb.zeroelem[m][q]=2;sb.cost[m][0]--;sb.cost[0][q]--;sb.cost[0][0]--;}}}for(q=1;q<=sb.matrixsize;q++){if(sb.cost[0][q]==1){for(p=1;p<=sb.matrixsize;p++)if(sb.cost[p][q]==0&&sb.zeroelem[p][q]==0)break;sb.zeroelem[p][q]=1;sb.cost[p][q]--;sb.cost[0][q]--;sb.cost[0][0]--;for(n=1;n<=sb.matrixsize;n++)if(sb.cost[p][n]==0&&sb.zeroelem[p][n]==0){sb.zeroelem[p][n]=2;sb.cost[p][0]--;sb.cost[0][n]--;sb.cost[0][0]--;}}}}if(sb.cost[0][0]>0)twozero(sb);elsejudge(sb,result);}sb=st;}}}void judge(matrix &sb,int result[501][2]){int i,j;int m;int n;int k;m=0;for(i=1;i<=sb.matrixsize;i++)for(j=1;j<=sb.matrixsize;j++)if(sb.zeroelem[i][j]==1)m++;if(m==sb.matrixsize){k=1;for(n=1;n<=result[0][0];n++){for(i=1;i<=sb.matrixsize;i++){for(j=1;j<=sb.matrixsize;j++)if(sb.zeroelem[i][j]==1)break;if(i<=sb.personnumber&&j<=sb.jobnumber)if(j!=result[k][1])break;k++;}if(i==sb.matrixsize+1)break;elsek=n*sb.matrixsize+1;}if(n>result[0][0]){k=result[0][0]*sb.matrixsize+1;for(i=1;i<=sb.matrixsize;i++)for(j=1;j<=sb.matrixsize;j++)if(sb.zeroelem[i][j]==1){result[k][0]=i;result[k++][1]=j;}result[0][0]++;}}else{refresh(sb);}}void refresh(matrix &sb){int i,j;float k;int p;k=0;for(i=1;i<=sb.matrixsize;i++){for(j=1;j<=sb.matrixsize;j++)if(sb.zeroelem[i][j]==1){sb.zeroelem[i][0]=1;break;}}while(k==0){k=1;for(i=1;i<=sb.matrixsize;i++)if(sb.zeroelem[i][0]==0){sb.zeroelem[i][0]=2;for(j=1;j<=sb.matrixsize;j++)if(sb.zeroelem[i][j]==2){sb.zeroelem[0][j]=1;}}for(j=1;j<=sb.matrixsize;j++){if(sb.zeroelem[0][j]==1){sb.zeroelem[0][j]=2;for(i=1;i<=sb.matrixsize;i++)if(sb.zeroelem[i][j]==1){sb.zeroelem[i][0]=0;k=0;}}}}p=0;k=0;for(i=1;i<=sb.matrixsize;i++){if(sb.zeroelem[i][0]==2){for(j=1;j<=sb.matrixsize;j++){if(sb.zeroelem[0][j]!=2)if(p==0){k=sb.cost[i][j];p=1;}else{if(sb.cost[i][j]<k)k=sb.cost[i][j];}}}}for(i=1;i<=sb.matrixsize;i++){if(sb.zeroelem[i][0]==2)for(j=1;j<=sb.matrixsize;j++)sb.cost[i][j]=sb.cost[i][j]-k;}for(j=1;j<=sb.matrixsize;j++){if(sb.zeroelem[0][j]==2)for(i=1;i<=sb.matrixsize;i++)sb.cost[i][j]=sb.cost[i][j]+k;}for(i=0;i<=sb.matrixsize;i++)for(j=0;j<=sb.matrixsize;j++)sb.zeroelem[i][j]=0;circlezero(sb);}void zeroout(matrix &sb){int i,j;float k;for(i=1;i<=sb.matrixsize;i++){k=sb.cost[i][1];for(j=2;j<=sb.matrixsize;j++)if(sb.cost[i][j]<k)k=sb.cost[i][j];for(j=1;j<=sb.matrixsize;j++)sb.cost[i][j]=sb.cost[i][j]-k;}for(j=1;j<=sb.matrixsize;j++){k=sb.cost[1][j];for(i=2;i<=sb.matrixsize;i++)if(sb.cost[i][j]<k)k=sb.cost[i][j];for(i=1;i<=sb.matrixsize;i++)sb.cost[i][j]=sb.cost[i][j]-k;}}void output(int result[501][2],matrix sb) {int k;int i;int j;int p;char w;float v;v=0;for(i=1;i<=sb.matrixsize;i++){v=v+sb.costforout[i][result[i][1]];}cout<<"最优解的目标函数值为"<<v;k=result[0][0];if(k>5){cout<<"解的个数超过了限制."<<endl;k=5;}for(i=1;i<=k;i++){cout<<"输入任意字符后输出第"<<i<<"种解."<<endl;cin>>w;p=(i-1)*sb.matrixsize+1;for(j=p;j<p+sb.matrixsize;j++)if(result[j][0]<=sb.personnumber&&result[j][1]<=sb.jobnumber)cout<<"第"<<result[j][0]<<"个人做第"<<result[j][1]<<"件工作."<<endl;}}void main(){result[0][0]=0;sb=input();zeroout(sb);circlezero(sb);output(result,sb);}4. 算例和结果:自己运算结果为:->⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎣⎡3302102512010321->⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎣⎡330110241200032034526635546967562543----⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎣⎡可以看出:第1人做第4件工作;第2人做第1件工作;第3人做第3件工作;第4人做第2件工作。

运筹(第四章整数规划)(1)

运筹(第四章整数规划)(1)

2023/2/22
28
(3)设法使每一行都有一个打括号的“0”元素。 按定理1继续对矩阵进行变换:
ⅰ)从矩阵未被直线覆盖的元素中找出最小者k,
ⅱ)对矩阵中无直线覆盖的行,令 ui k ,有直 线覆盖的列,令 v j k 。其余为0。
ⅲ)对矩阵的每个元素计算 aij ui v j ,得到 一个新矩阵,转第三步重复进行,直至每一行都有 一打括号的0元素。
2023/2/22
3
§1.2 整数规划的求解特点
求整数解的线性规划问题,不是用四舍五入法或
去尾法对性规划的非整数解加以处理就能解决的,
用枚举法又往往会计算量太大,所以要用整数规
划的特定方法加以解决。
例: 求解下列整数规划:
max z 3x1 2x2
2x1 3x2 14
s.t
x1
0.5x2
2023/2/22
14
解:设x j 表示代号为j的包装箱的订做数量。
0, 不订j包装箱 y j 1, 订j包装箱
目标函数
6
min z 1200 y j 5x1 8x2 10x3 j 1
12.1x4 16.3x5 18.2x6
约束条件
x j My j , j 1,...6
2023/2/22
i 1
5
8 xij 15 ,i 1,...4
j 1
5
7 xij 12 , i 5,6
j 1 5
yij 3,
i 1,..., 6
j 1
6
yij 3,
i 1
j 1,...,5
y5 j y6 j 1 j 1,..., 5
每天开放14小时 大学生值班8-15小时 研究生值班7-12小时 每周不超过3次

匈牙利算法——精选推荐

匈牙利算法——精选推荐

二分图最优匹配:对于二分图的每条边都有一个权(非负),要求一种完备匹配方案,使得所有匹配边的权和最大,记做最优完备匹配。

(特殊的,当所有边的权为1时,就是最大完备匹配问题)解二分图最优匹配问题可用穷举的方法,但穷举的效率=n!,所以我们需要更加优秀的算法。

先说一个定理:设M是一个带权完全二分图G的一个完备匹配,给每个顶点一个可行顶标(第i个x顶点的可行标用lx[i]表示,第j个y顶点的可行标用ly[j]表示),如果对所有的边(i,j) in G,都有lx[i]+ly[j]>=w[i,j]成立(w[i,j]表示边的权),且对所有的边(i,j) in M,都有lx[i]+ly[j]=w[i,j]成立,则M是图G的一个最优匹配。

Kuhn-Munkras算法(即KM算法)流程:v(1)初始化可行顶标的值v(2)用匈牙利算法寻找完备匹配v(3)若未找到完备匹配则修改可行顶标的值v(4)重复(2)(3)直到找到相等子图的完备匹配为止KM算法主要就是控制怎样修改可行顶标的策略使得最终可以达到一个完美匹配,首先任意设置可行顶标(如每个X节点的可行顶标设为它出发的所有弧的最大权,Y节点的可行顶标设为0),然后在相等子图中寻找增广路,找到增广路就沿着增广路增广。

而如果没有找到增广路呢,那么就考虑所有现在在匈牙利树中的X节点(记为S集合),所有现在在匈牙利树中的Y节点(记为T 集合),考察所有一段在S集合,一段在not T集合中的弧,取delta = min {l(xi)+l(yj)-w(xi,yj) , | xi in S, yj in not T} 。

明显的,当我们把所有S集合中的l(xi)减少delta之后,一定会有至少一条属于(S, not T)的边进入相等子图,进而可以继续扩展匈牙利树,为了保证原来属于(S,T )的边不退出相等子图,把所有在T 集合中的点的可行顶标增加delta。

随后匈牙利树继续扩展,如果新加入匈牙利树的Y节点是未盖点,那么找到增广路,否则把该节点的对应的X匹配点加入匈牙利树继续尝试增广。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

第四章 整数规划
B、任务分配问题的数学模型
设:xij为第i个工人分配去做第j项任务 aij为第i个工人为完成第 j 项任务时的工时消耗。则
1 当分配第j项任务给第i个工人时 x ij 0 当不分配第j项任务给第i个工人时
i,j=1,2,…,n
由于每人只允许分 配一项任务, 且每项任务只能由 一人来完成, 故其数学模型、目 标函数及约束条件 如下:
定理1
设一个任务分配问题的效率矩阵为{aij},若{aij}中每一行元素分别减去 一个常数ui,每一列元素分别减去一个常数vj,得到一个新的效率矩阵{bij}, 其中一个元素bij=aij-ui-vj,则{bij}的最优解等价于{aij}的最优解。
第四章 整数规划
定理2
若一个方阵中的一部分元素为零,一部分元素非零,则覆盖方阵中所 有元素的最少直线等于位于不同行、不同列的零元素最多个数。
m
m
a ij x ij
这样得到新效率矩阵的最优解,根据定理 1,他也是原问题的最优解。 (3)验证最优解的方法:设法用最少的直线数覆盖方阵中位于不同行、 不同列的零元素。 如果覆盖所有零元素的最少直线数等于m,则得到最优解,否则不是
第四章 整数规划
3、匈牙利解法的计算步骤: 第一步:效率矩阵的初始变换----零元素的获得 (1)行变换:找出每行的最小元素,该行各元素减去这个最小元素。 (2)列变换:找出每列的最小元素,该列各元素减去这个最小元素。
分配问题与匈牙利法
C (95 c ij )
解: M=95,令
10 0 C = 13 9
0 1 X= 0 0
3 8 12 5
22 17 16 15
5 0 5 7
0 0 1 0
用匈牙利法求解C’,最优解为:
1 0 0 0 0 0 0 1

非最优阵的变换
第四章 整数规划
3、匈牙利解法的计算步骤: 第四步:重新标号
抹掉原来的标号,回到最优性检验,并进行重新标号,直到得到最优解

0 2 1 // 0
Hale Waihona Puke // 0试分配过程// 0
7
4 0 2
0
2 4
2 4 0 0
0 2 1 0 //
经变换后的效率矩阵,其每行、每列至少有一个零元素。
4 9 8 6
1
8 4 5
8
4
6 7
2 3 7 5 3 5 2 4
0 4 1 3
7 0 3 5
1 0 3 2 0 2 1 0
0
1 8 4
0
7 4
0
表所示,最终表为最优解,此时甲→D,乙→B,丙→A,丁→C 目标函数为 maxf(x)=15+7+13+15=50
分配问题与匈牙利法
非标准型的指派问题: 匈牙利法的条件是:模型求最小值、效率cij≥0。 当遇到各种非标准形式的指派问题时,处理方 法是先将其转化为标准形式,然后用匈牙利法 来求解。
13 8 7 2
2
1 7 0 12 0 0 4 2
6
11
0
4 2
11 8 9 0 1 3 2
1 8 4
0 1 1 0 8 0 0 4
零元素上打上括号,并划去打括号零元素同列的其他零元素。 如果该行没有零元素,或有两个或多个零元素(已划去的不记在 内),则转下行 (2)逐列检查:依照行检查的方法从第一列开始逐列检查。
表 最优性检验
0 2 2 1 0 7 1 (0) 4 0 3 2 1 3 0 2 3 5 0 1 1 4 (0) 3 1 3 ( 0) 3 5 0 /
7
4
0
4
0 2
2
2 4 // 0 0
0 2 1 0//
// 0
7
4
0
4
0 2
2
2 4 // 0 0
第四章 整数规划
D、目标函数为最大的任务分配问题
如果目标函数为MAX型,则不属于标准的任务分配模型,不 能直接运用匈牙利解法求解,这就需要先对max模型进行变换, 然后再求解。 例:有甲、乙、丙、丁4人分别操作4台机器,每个工人操作不 同机器时的产值如表,求对4个工人分配不同机器时总产 值最大的方案。
第四章 整数规划
步骤如下: 对无()的行打√ 对打√行上所有零元素的列打√ 在打√的列上有()的行打√ 重复步骤,直到过程结束 对没有打√的行划横线,对所有打√的列划垂线,这时得 到覆盖矩阵中所有零的最少直线数
( 0) 2 2 1 1 4 (0) 3 1 3 (0) // 3 5 0 0// 7 ( 0) 2 2 1 1 4 (0) 3 1 3 (0) 3 5 0 0 7
第四章 整数规划
3、匈牙利解法的计算步骤: 第三步:非最优阵的变换——零元素的移动
当表中的覆盖所有零的直线数小于m时,得到的不是最优解,因此需要 对表中矩阵进一步进行变换,过程如下: ① 在未被直线覆盖的所有元素中找出最小元素 ② 所有未被直线覆盖的元素都减去这个最小元素 ③ 覆盖线十字交叉处的元素都加上这个最小元素
匈牙利数学家考尼格(Konig)提出的,得名匈牙利解法 (the Hungarian Method of Assignment) 1、匈牙利解法的基本思想---适用条件 基于任务分配问题的标准型,标准型要满足下述三个条件: (1)目标要求为min (2)效率矩阵{aij}为n阶方阵 (3)阵中所有元素aij≥0,且为常数
即甲安排做第二项工作、乙做第一项、丙做第四项、丁做 第三项, 最高总分Z=92+95+90+80=357
分配问题与匈牙利法
2. 不平衡的指派问题
当人数m大于工作数n时,加上m-n项虚拟工作,例如:
5 11 8 6 3 9 6 14 4 2 10 3 17 5 1 5 11 8 6 3 9 6 14 4 2 10 3 17 5 1 0 0 0 0 0 0 0 0 0 0
若某人可做几件事,则将该人化作相同的几个“人”来接受 指派,且费用系数取值相同。 例如:丙可以同时任职A和C工作,求最优指派方案。
甲 乙 丙 15 6 10 20 5 13 10 4 16 9 7 17
15 6 10 10 20 5 13 13 10 4 16 16 9 7 17 17
minf
m
x

i 1 j 1
m m
a ij x ij
x 1 ij j 1 m x ij 1 i 1 x 0 ij
i 1,2, , m j 1,2, , m
或1
第四章 整数规划
C、任务分配问题的解法-----匈牙利解法
/ 0
7
第四章 整数规划
最优性检验后可能可能出现的情况
① 每行都有一个零元素标有括号,显然这些括号零在不同行 和不同列,因此得到最优解。 ②每行、每列都有两个或更多的零,这是从剩有零元素最少的 行开始,比较这行各零元素所在列中零元素的个数,选择零 元素少的那列的这个零元素打括号,划掉同行同列的其他零 元素,然后重复以上步骤,直到所有零都做了标记。 ③矩阵中所有零都做了标记,但标有()的零元素个数少于 m,此时就可以找出能覆盖矩阵中所有零元素的最少直线的 集合。 步骤如下:
分配问题与匈牙利法
4. 某事一定不能由某人做的指派问题
将该人做此事的效率系数取做足够大的数,可用M表示

例 分配甲、乙、丙、丁四个人去完成A、B、C、D、E五 项任务。每个人完成各项任务的时间如表所示。由于任务 数多于人数,考虑任务E必须完成,其他4项中可任选3项完 成。试确定最优分配方案,使完成任务的总时间最少。
当人数m小于工作数n时,加上n-m个人,例如
15 6 10 20 5 13 10 4 16 9 7 17
15 6 10 0 20 5 13 0 10 4 16 0 9 7 17 0
分配问题与匈牙利法
3. 一个人可做几件事的指派问题
人员 任务 A 25 B 29 C 31 D 42 E 37
0 4 1 3
7 0 3 5
1 3 0 0
表 效率 矩阵 的 初始 变换
第二步:最优性检验
检查能否找到m个位于不同行、不同列的零元素,即检查覆盖所有零元 素的直线是否为m条
第四章 整数规划
3、匈牙利解法的计算步骤: (1)逐行检查:从第一行开始,如果该行只有一个零元素,就在这个
人员 任务 A 25 B 29 C 31 D 42 E 37


丙 丁
39
34 24
38
27 42
26
28 36
20
40 23
33
32 45
分配问题与匈牙利法
解: 1) 这是不平衡的指派问题,首先转换为标准型,再用 匈牙利法求解。 2) 由于任务数多于人数,所以假定一名虚拟人,设为戊。 因为工作E必须完成,故设戊完成E的时间为M(M为非 常大的数),其余效率系数为0,则标准型的效率矩阵表 示为:
分配问题与匈牙利法
1. 最大化指派问题
处理方法:设m为最大化指派问题系数矩阵C中最大元素。
令矩阵B=(m-cij)nn则以B为系数矩阵的最小化指派问题 和原问题有相同的最优解。
例 某人事部门拟招聘4人任职4项工作,对他们综合 考评的 得分如下表(满分100分),如何安排工作使 总分最多。
相关文档
最新文档