运筹学第17讲复习分配问题与匈牙利法
运筹学匈牙利法

运筹学匈牙利法运筹学匈牙利法(Hungarian Algorithm),也叫匈牙利算法,是解决二部图最大(小)权完美匹配(也称作二分图最大权匹配、二分图最小点覆盖)问题的经典算法,是由匈牙利数学家Kuhn和Harold W. Kuhn发明的,属于贪心算法的一种。
问题描述在一个二分图中,每个节点分别属于两个特定集合。
找到一种匹配,使得所有内部的节点对都有连边,并且找到一种匹配方案,使得该方案的边权和最大。
应用场景匈牙利算法的应用场景较为广泛,比如在生产调度、货车调度、学生对导师的指定、电影的推荐等领域内,都有广泛的应用。
算法流程匈牙利算法的伪代码描述如下:进行循环ɑ、选择一点未匹配的点a作为起点,它在二分图的左边β、找出a所有未匹配的点作为下一层节点ɣ、对下一层的每个节点,如果它在右边未匹配,直接匹配ɛ、如果遇到一个已经匹配的节点,进入下一圈,考虑和它匹配的情况δ、对已经匹配的点,将它已经匹配的点拿出来,作为下一层节点,标记这个点作为已被搜索过ε、将这个点作为当前层的虚拟点,没人配它,看能否为它找到和它匹配的点ζ、如果能匹配到它的伴侣,令它们成对被匹配最后输出最大权匹配。
算法优缺点优点:相比于暴力求解二分图最大权匹配来说,匈牙利算法具有优秀的解决效率和高效的时间复杂度,可以在多项式时间(O(n^3))内解决二分图最大权匹配问题。
缺点:当二分图较大时,匈牙利算法还是有很大的计算复杂度,复杂度不佳,算法有效性差。
此时就需要改进算法或者使用其他算法。
总结匈牙利算法是一个常见的解决二分图最大权匹配问题的算法,由于其简洁、易用、效率优秀等特性,广泛应用于学术和实际问题中。
匈牙利算法虽然在处理较大规模问题时效率不佳,但仍然是一种值得掌握的经典算法。
分配问题与匈牙利法说课讲解

0 13 11 2
10 4 14 15 4
9 14 16 13 9
7 8 11 9 7
6 0 10 11
0 5 7 4
0 1
4
2
2)试指派(找独立0元素) 4 2
0 13 7 0
6 0 6 9
0 5 3 2
0 1 0 0
0Ø 13 7 ◎0
6 ◎0 6 9
0◎ 5 3 2
0Ø
分配问题与匈牙利法
Page 1
指派问题的数学模型的标准形式: 设n 个人被分配去做n 件工作,规定每个人只做一件工作,
每件工作只有一个人去做。已知第i个人去做第j 件工作的效率 ( 时间或费用)为Cij(i=1.2…n;j=1.2…n)并假设Cij ≥0。问应 如何分配才能使总效率( 时间或费用)最高? 设决策变量
若仍有没有划圈的0元素,且同行(列)的0元素至少有两个,比 较这行各0元素所在列中0元素的数目,选择0元素少这个0元素加 圈(表示选择性多的要“礼让”选择性少的)。然后划掉同行同列 的其它0元素。可反复进行,直到所有0元素都已圈出和划掉为止。
分配问题与匈牙利法
Page 6
若◎ 元素的数目m 等于矩阵的阶数n(即:m=n),那么这指
所有0元素的最少直线数 l 。
注:l 应等于m,若不相等,说明试指派过程有误,回到第2步,另行试 指派;若 l=m < n,表示还不能确定最优指派方案,须再变换当前的系 数矩阵,以找到n个独立的0元素,为此转第4步。
分配问题与匈牙利法
Page 7
4) 变换矩阵(bij)以增加0元素
在没有被直线通过的所有元素中找出最小值,没有被直线通过 的所有元素减去这个最小元素;直线交点处的元素加上这个最小 值。新系数矩阵的最优解和原问题仍相同。转回第2步。
分配问题指派问题与匈牙利法课件

分派方案满足下述两个条件:
• 任一个工人都不能去做两件或两件以上的工作 1.任一件工作都不能同时接受两个及以上的工人去做
分配问题指派问题与匈牙利法课件
标准形式的分配问题
n个人 n件事
每件事必有且只有一个人去做 每个人必做且只做一件事
5 0 2 0 2
2
3
0
0
0
0 10 5 7 2
9
8
0
0
4
0 6 3 6 5
圈0个数4 < n=5
5 0 2 0 2
2
3
0
0
0
0 10 5 7 2
9
8
0
0
4
0 6 3 6 5
分配问题指派问题与匈牙利法课件
⑥找未被直线覆盖的最小数字k;
⑦对矩阵的每行:当该行有直线覆盖时,令ui=0; 当 该 行 无 直 线 覆 盖 时 , 令 ui=k 。
⑩再次寻找独立零元素
逐列检验
4 8 7 15 12
7 9 17 14 10
6
9
12
8
7
6 7 14 6 10
6
9
12
10
6
0 3 0 11 8
0 0 6 6 2
0
1
2
1
0
0 0 5 0 4
0
2
3
4
0
0 0 1 0 0
0 1 0 0 0
0
0
0
0
1
0 0 0 1 0
分配问题指派问题与匈牙利法课件
数学模型
运筹学指派问题的匈牙利法

运筹学课程设计指派问题的匈牙利法专业:姓名:学号: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件工作。
分配问题与匈牙利法

0 13 11 2
10 4 14 15 4
9 14 16 13 9
7 8 11 9 7
6 0 10 11
0 5 7 4
0 1
4
2
2)试指派(找独立0元素) 4 2
0 13 7 0 6 0 6 9 0 5 3 2 0 1 0 0
0Ø 13 7 ◎0
6 ◎0 6 9
0◎ 5 3 2
0Ø
分配问题与匈牙利法
Page 24
1. 最大化指派问题
处理方法:设m为最大化指派问题系数矩阵C中最大元素。
令矩阵B=(m-cij)nn则以B为系数矩阵的最小化指派问题和
原问题有相同的最优解。
例4.9 某人事部门拟招聘4人任职4项工作,对他们综合考评的 得分如下表(满分100分),如何安排工作使总分最多。
分配问题与匈牙利法
Page 7
例4.6 有一份中文说明书,需译成英、日、德、俄四种文字, 分别记作A、B、C、D。现有甲、乙、丙、丁四人,他们将 中文说明书译成不同语种的说明书所需时间如下表所示,问 如何分派任务,可使总时间最少?
任务
A
B
C
D
人员
甲
6
7
11
2
乙
4
5
9
8
丙
3
1
10
4
丁
5
9
8
2
分配问题与匈牙利法
Page 8
解:1)变换系数矩阵,增加0元素。
6 7 11 2 2
4 5 9 0
(cij
)
4 3
5 1
9 10
8 4 4 1
5 9 8 2 2
0 1 5 4 2 0 9 3 3 7 6 0
线性规划例题5分配问题及匈牙利算法

直角坐标系。 • (2)对每个约束(包括非负约束)条件,
先取其等式在坐标系中作出直线,通过
判断确定不等式所决定的半平面。各约束半 平面交出来的区域(存在或不存在),若存在, 其中的点表示的解称为此线性规划的可行解。 这些符合约束限制的点集合,称为可行集或 可行域。
同时,我们有一个追求目标,即获
取最大利润。于是可写出目标函数z
为相应的生产计划可以获得的总利
润:z=40x1+30x2 +50x3
【解】设x1、x2、x3 分别为甲、乙、丙三种产品 的产量数学模型为:
mZ a 4 x x 1 0 3x 2 0 5x 3 0
3 x1 x 2 2 x3 200
问:如何分配,能使所需的 总时间最少?
人 工作 甲 乙 丙 丁
译英文 2 10 译日文 15 4 译德文 13 14 译俄文 4 15
97 14 8 16 11 13 9
1.1 数学模型 Mathematical Model
线性规划(Linear Programming,缩写为LP)是运筹学的重 要分支之一,在实际中应用得较广泛,其方法也较成熟, 借助计算机,使得计算更方便,应用领域更广泛和深入。
怎样辨别一个模型是线性规划模型?其特征是: 1.解决问题的目标函数是多个决策变量的线性函 数,通常是求最大值或 最小值; 2.解决问题的约束条件是一组多个决策变量 的线 性不等式或等式。
书本还例举了诸如合理用料问题;配料问题;投资问题;均衡配 套生产问题等.
• 线性规划的一般模型
max(min)Z c1x1 c2 x2 L cn xn
6
x 1 0 、 x 2 0
指派问题与匈牙利解法

指派问题与匈⽛利解法指派问题概述:实际中,会遇到这样的问题,有n项不同的任务,需要n个⼈分别完成其中的1项,每个⼈完成任务的时间不⼀样。
于是就有⼀个问题,如何分配任务使得花费时间最少。
通俗来讲,就是n*n矩阵中,选取n个元素,每⾏每列各有1个元素,使得和最⼩。
如下图:指派问题性质:指派问题的最优解有这样⼀个性质,若从矩阵的⼀⾏(列)各元素中分别减去该⾏(列)的最⼩元素,得到归约矩阵,其最优解和原矩阵的最优解相同.匈⽛利法:12797989666717121491514661041071091.⾏归约:每⾏元素减去该⾏的最⼩元素502022300001057298004063652.列归约:每列元素减去该列的最⼩元素502022300001057298004063653.试指派:(1)找到未被画线的含0元素最少的⾏列,即,遍历所有未被画线的0元素,看下该0元素所在的⾏列⼀共有多少个0,最终选取最少个数的那个0元素。
(2)找到该⾏列中未被画线的0元素,这就是⼀个独⽴0元素。
对该0元素所在⾏和列画线。
50202230000105729800406365502022300001057298004063655020223000010572980040636550202230000105729800406365(3)暂时不看被线覆盖的元素,重复(1)(2)直到没有线可以画。
(4)根据(2)找到的0元素个数判断,找到n个独⽴0元素则Success,⼩于n个则Fail.(本例⼦中,n=5,可以看到,第⼀次试指派之后,独⽴0元素有4个,不符合)4.画盖0线:⽬标:做最少的直线数覆盖所有0元素,直线数就是独⽴0元素的个数。
注意:这跟3的线不同;不能⽤贪⼼法去画线,⽐如1 0 01 1 01 0 1若先画横的,则得画3条线,实际只需2条;若先画竖的,将矩阵转置后同理。
步骤3得出的独⽴0元素的位置50202230000105729800406365(1)对没有独⽴0元素的⾏打勾、(2)对打勾的⾏所含0元素的列打勾(3)对所有打勾的列中所含独⽴0元素的⾏打勾(4)重复(2)(3)直到没有不能再打勾(5)对打勾的列和没有打勾的⾏画画线,这就是最⼩盖0线。
分配问题与Hungarian算法

分配问题与Hungarian算法分配问题与Hungarian算法分配问题指派问题匈⽛利算法匈⽛利⽅法是⼀种能够在多项式时间内解决分配问题(assignment problem)的组合优化算法。
它由Harold Kuhn 与1955年发展并提出,由于该算法很⼤程度上依赖于先前两位匈⽛利数学家:Denes Konig 和 Jeno Egervary,所以被命名为“匈⽛利⽅法”。
1957年James Munkres重新审视了这个⽅法,证明发现该⽅法是严格polynomial的,所以之后该⽅法也被称为Kuhn-Munkres 算法或者Munkres分配算法。
原始的匈⽛利算法的时间复杂度是,然⽽之后Edmonds和Karp,以及Tomizawa独⽴发现经过⼀定的修改,该算法能改达到的时间复杂度。
Ford和Fulkerson将该⽅法扩展到⼀般运输问题的求解上。
2006年,研究发现Carl Custav Jacobi在19实际就解决了assignment问题,并且在其逝世后的1890年求解过程被以拉丁语形式发表。
指派问题匈⽛利法解决的指派问题应该具有两个约束条件workes 和tasks的数⽬应该相同,即o2o问题。
求解的是最⼩化问题,如⼯作时间的最⼩化、费⽤的最⼩化等等指派问题⽰例:有三个workers: Jim, Steve和Alan,现在有3个⼯作:clean the bathroom, sweep the floors和wash the windows需要交给这三个⼈,每个⼈只能完成⼀个任务,对应的cost matrix如下---Clean bathroom Sweep floors Wash windowsJim$2$3$3Steve$3$2$3Alan$3$3$2那么如何分配任务是开销最⼩就是⼀个指派问题匈⽛利法步骤问题: 假定某单位有甲、⼄、丙、丁、戊五个员⼯,现需要完成A、B、C、D、E五项任务,每个员⼯完成某项任务的时间如下图所⽰,应该如何分配任务,才能保证完成任务所需要的时间开销最⼩?1476015762594.jpg解:1. 写出系数矩阵2. 更新系数矩阵,使系数矩阵的每⼀⾏每⼀列都减去该⾏该列的最⼩值,保证每⼀⾏每⼀列都有0元素出现,参见定理2.3. 选择只有⼀个0元素的⾏或列将该0元素标注为独⽴0元素,并将该0元素所在的列或⾏中0元素划掉,直⾄找不到满⾜条件的⾏或列,需要注意的是在循环时,划掉的0元素不再视为0元素。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
2 1
(4,1) 2x1+3x2=14
x1+x2=5
0
x1
1 2 34 5 6 7 8 9
确定割平面方程的练习:
x 2 ( 03 4 ) x 3 ( 01 4 ) x 4 1 3 4
x141x341x4
3 4
x234x341x474
x 1 ( 1 3 4 ) x 3 ( 0 1 4 ) x 4 0 3 4
即:
1 21 2x31 2x4 0
加上松弛变量之后得到
1 21 2x31 2x4x5 0
根据右端为整数且变量非负的要求,得到:
1 21 2x31 2x4
11 2
第3步.在最优单纯形表中求解增加约束条件后的LP问题的最优解;
cj CB 基 b
2
x2
21 2
3
x1
31 4
0c
第四章 整数规划与分配问题
Integer Programming,简称IP
• 整数规划的特点及作用 • 分枝定界法 • 割平面法 • 分配问题与匈牙利法 • 应用举例
整数规划的特点
整数规划是研究决策变量只能取正整数的一类规划问题。 有纯整数规划、混合整数规划与0-1整数规划等类型。我 们只研究线性整数规划。
21 2
x1
31 4
cj zj
将上式所有常数分写成整数与正分数之和:
23 00
x1 x2 x3 x4
0 1 1 1
22
1
0
1 4
3 4
0 0 15
44
x 2 ( 0 1 2 ) x 3 ( 1 1 2 ) x 4 2 1 2
分数移项到右端,整数项到左端:
x2x421 21 2x31 2x4
割平面法的基础仍然是用解线性规划的方法去解整数规 划问题:首先不考虑变量为整数这一条件,但增加线性约束 条件(Gomory约束,称为割平面),使得原可行解域中切掉 一部分,这部分只包含非整数解,但没切割掉任何整数可行 解,切除的结果使整数解可能成为顶点。
割平面法的步骤
求松弛问题的 最优基可行解
判断是否 为整数解
31 4
0c
j x5
z
j
1 2
cj zj
2 x2 2
3
x1
31 2
0 x3 1
cj zj
23 00 0
x 1 x 2 x 3 x 4 x5
0
1
1 1 22
0
1
0
1 4
3 4
0
0 0 0
00 0
11 142
15 524
1 0
44
0 1 0 1 1
2
1 0 0 1 1
束
分别用图解法求得最优解
6
5
X(1)=(3,2.67)T, Z(1)=14.33
4
X(2)=(4,1)T,
Z(2)=14
3
Z(1) > Z(2) =14
2
(4,1) (1)
1
子问题2停止分枝,其整数解作为界;
0 1 2 3 4 5 6 7 8 9 x子1 问题1对x2=2.67进行分枝
子问题1
子问题2
分配问题的提出【指派问题】
若干项工作或任务需要若干个人去完成。由于 每人的知识、能力、经验的不同,故各人完成不同 任务所需要的时间不同(或其他资源)。
3
x1
31 4
cj zj
23 00
x1 x2 x3 x4
0
1
1 1 22
1
0
1 4
3 4
0 0 15
44
第2步.寻找割平面方程;
cj
Gomory 约束
C一个基变 2
量,并写出该行在最终表中的约束方程
3
x21 2x31 2x4
21 2
x2
2 x1 3x2 14
4xx1 1
x2
2 x2 2
18 3 分枝
约
束
x1 , x2 0
max Z 3x1 2 x2
2 x1 3 x2 14
4xx1 1
2x2 18 3
x2 3 分枝约束
x1 , x2 0
添加x2≤2
问题(3) x1=3,x2=2
Z(3)=13
问题(1) x1=3,x2=8/3 Z(1)=14.33
添加x2≥3
问题(4) x1=2.5,x2=3
Z(4)=13.5
问题(2)
√ x1=4,x2=1 Z(2)=14
分枝问题解可能出现的情况表
序号
问题 1
问题 2
说明
1
无可行解
无可行解
整数规划无可行解
将系数和常数项都分解为整数和正分数之和并移项得:
x1
x3
3 4
3 4
x3
1 4
x4
0
x2
1
3 4
3 4
x3
1 4
x4
0
第四章 整数规划与分配问题
Integer Programming,简称IP
• 整数规划的特点及作用 • 分枝定界法 • 割平面法 • 分配问题与匈牙利法 • 应用举例
子问题46
5 4
max Z 3x1 2 x2
2 x1 3x2 14
4xx1 1
x2
2 x2 2
18 3 分枝
约
束
x1 , x2 0
max Z 3x1 2 x2
2 x1 3 x2 14
4xx1 1
2x2 18 3
分枝定界法
实质:在保留原问题全部整数可行解的前提下,将原 问题分枝为若干容易求解的子问题,并利用子问题的 整数解的目标值来判定分枝的界限<定界>。 分 枝
边界
【例】某厂拟购进甲、乙两类机床生产新产品。已知两类机床进价
分别为2万元和3万元,安装占地面积分别为4m2和2m2,投产后的收 益分别为3百元/日和2百元/日。厂方仅有资金14万元,安装面积18m2, 为使收益最大,厂方应购进甲、乙机床各多少台?
j x5
z
j
1 2
cj zj
2 x2 2
3
x1
31 2
0 x3 1
cj zj
23 00 0
x 1 x 2 x 3 x 4 x5
0
1
1 1 22
0
1
0
1 4
3 4
0
0 0 0
00 0
11 142
15 524
1 0
44
0 1 0 1 1
2
1 0 0 1 1
2
0 0 1 1 2
(2)
4x1+2x2=18
6
5
4
1、去掉变量为整数约束,可 3
用图解法求得最优解;
2 1
(3.25,2.5)T (1) 2x1+3x2=14
x1=3.25非整数,进行分枝
0 1 2 3 4 5 6 7 8 9 x1
x1=3.25非整数,进行分枝
2、得两个子问题的数学模型:
子问题(1)
max Z 3 x 1 2 x 2
子问题(1)
Z(1) < Z(2) =14
max Z 3 x 1 2 x 2
2 x 1 3 x 2 14
子问题2停止分枝,其整数解作为界;
4 x x
x
1 1
12 3
x分2 枝1约8
,x2 0
束
子问题1对x2=2.67进行分枝
子问题(3)
子问题(4)
x2
写出该行在最终表中的约束方程
根据右端为整数且变量非负的要求,得到:
1
1
x1
x4
2
x5
3 2
1 2
1 2
x5
0
将上式所有常数分写成整数与正分数之和: 加上松弛变量之后得到
x1x4 ( 11 2) x531 2
分数移项到右端,整数项到左端:
11 22
x5
x6
0
11 x1x4x5322x5
分别用图解法求得最优解
最优解:X*=X(2) =(4,1)T 最优值:Z*=14
X(3)=(3,2)T, X(4)=(2.5,3)T,
Z(3)=13 Z(4)=13.5
Z(3) < Z(2) ; Z(4) < Z(2)
添加x1≤3
问题(0) x1=3.25,x2=2.5
Z(0)=14.75
添加x1≥4
2
0 0 1 1 2
0 0 0 1 1
2
1 21 2x31 2x4x5 0
最优解仍为非整数解 继续寻找Gomory约束
2
x2 2 0 1
0 1 1
2
3
x1
31 2
1
0 0 1 1
2
0 x3 1
0 0 1 1 2
cj zj
0 0 0 1 1
2
最优解仍为非整数解 继续寻找Gomory约束
Z(1) < Z(2) =14
max Z 3 x 1 2 x 2
2 x 1 3 x 2 14
子问题2停止分枝,其整数解作为界;
4 x x
x
1 1
12 3
x分2 枝1约8