匈牙利法的指派问题 共33页
匈牙利法解决人数及任务数不等的指派问题
![匈牙利法解决人数及任务数不等的指派问题](https://img.taocdn.com/s3/m/fce5a9030975f46526d3e165.png)
匈牙利法解决人数与任务数不等的指派问题于凯重庆科技学院经济管理学院物流专业重庆沙坪坝区摘要:本文将讨论运筹学中的指派问题,而且属于非标准指派问题,即人数与任务数不相等的指派问题,应当视为一个多目标决策问题,首先要求指派给个人任务数目两两之间相差不能超过1,其次要求所需总时间最少,并且给岀了该类问题的求解方法。
关键词:运筹学指派问题匈牙利算法系数矩阵解矩阵引言:在日常的生产生活中常遇到这样的问题:有n项任务,有n个人员可以去承担这n 项任务,但由于每位人员的特点与专长不同,各对象完成各项任务所用的时间费用或效益不同:有因任务性质要求和管理上需要等原因,每项任务只能由一个人员承担来完成,这就涉及到应该指派哪个人员去完成哪项任务,才能使完成n项任务花费总时间最短,总费用最少, 产生的总效益最佳。
我们把这类最优匹配问题称为指派问题或分配问题。
1. 指派问题的解法——匈牙利法早在1955年库恩(w.w.ku.hn)就提出了指派问题的解法,该方法是以匈牙利数学家康尼格(koning)提岀的一个关于矩阵中0元素的定理为基础,因此得爼匈牙利法(The Hungonrian Method of Assignment)1.1匈牙利解法的基本原理和解题思路直观的讲,求指派问题的最优方案就是要在n阶系数矩阵中找出n个分布于不用行不同列的元素使得他们的和最小。
而指派问题的最优解又有这样的性质:若从系数矩阵C (ij)的一行(列)各元素都减去该行(列)的最小元素,得到新矩阵CB (ij),那么以CB (ij)为系数矩阵求得的最优解和原系数矩阵C (ij)求得的最优解相同。
由于经过初等变换得到的新矩阵CB (ij)中每行(列)的最小元素均为"O”,因此求原指派问题C (ij)的最优方案就等于在新矩阵CB (ij)中找出n个分布于不同行不同列的"O”元素(简称为“独立O元素”),这些独立O元素就是CB (ij)的最优解,同时与其对应的原系数矩阵的最优解。
求解指派问题的匈牙利算法.doc
![求解指派问题的匈牙利算法.doc](https://img.taocdn.com/s3/m/d0689452f01dc281e53af0b0.png)
3.2 求解指派问题的匈牙利算法由于指派问题的特殊性,又存在着由匈牙利数学家D.Konig 提出的更为简便的解法—匈牙利算法。
算法主要依据以下事实:如果系数矩阵)(ij c C =一行(或一列)中每一元素都加上或减去同一个数,得到一个新矩阵)(ij b B = ,则以C 或B 为系数矩阵的指派问题具有相同的最优指派。
利用上述性质,可将原系数阵C 变换为含零元素较多的新系数阵B ,而最优解不变。
若能在B 中找出n 个位于不同行不同列的零元素,令解矩阵中相应位置的元素取值为1,其它元素取值为零,则所得该解是以B 为系数阵的指派问题的最优解,从而也是原问题的最优解。
由C 到B 的转换可通过先让矩阵C 的每行元素均减去其所在行的最小元素得矩阵D ,D 的每列元素再减去其所在列的最小元素得以实现。
下面通过一例子来说明该算法。
例7 求解指派问题,其系数矩阵为⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎣⎡=16221917171822241819211722191516C 解 将第一行元素减去此行中的最小元素15,同样,第二行元素减去17,第三行元素减去17,最后一行的元素减去16,得⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎣⎡=06310157124074011B 再将第3列元素各减去1,得⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎣⎡=****20531005711407301B 以2B 为系数矩阵的指派问题有最优指派⎪⎪⎭⎫ ⎝⎛43124321 由等价性,它也是例7的最优指派。
有时问题会稍复杂一些。
例8 求解系数矩阵C 的指派问题⎥⎥⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎢⎢⎣⎡=61071041066141512141217766698979712C 解:先作等价变换如下∨∨∨⎥⎥⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎢⎢⎣⎡→⎥⎥⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎢⎢⎣⎡----- 2636040*08957510*00*0032202*056107104106614151214121776669897971246767 容易看出,从变换后的矩阵中只能选出四个位于不同行不同列的零元素,但5=n ,最优指派还无法看出。
指派问题的匈牙利法
![指派问题的匈牙利法](https://img.taocdn.com/s3/m/3b97bed73186bceb19e8bb56.png)
4 0 2 3
5 9 0 1 5 4 0 9 3 7 6 0
4 0 2 3
5 4 0 1 0 4 0 4 3 7 1 0
第二步,试指派: 第二步,试指派:
-5
举例说明 1)表上作业法 2)匈牙利法
例 有四个工人和四台不同的机床,每位工人在不 同的机床上完成给定的任务的工时如表5.12所示, 问安排哪位工人操作哪一台机床可使总工时最少?
任务1 工人1 工人2 工人3 工人4 2 15 13 4
任务2 10 4 14 7
任务3 3 14 16 13
任务4 7 8 11 9
0 0 1 0
0 0 1 1 0 0 0 0 0 0 1 0
例二、 例二、 有一份中文说明书,需译成英、 有一份中文说明书,需译成英、日、德、俄四种
文字,分别记作A、 、 、 。现有甲、 文字,分别记作 、B、C、D。现有甲、乙、丙、丁四 人,他们将中文说明书译成不同语种的说明书所需时 间如下表所示,问如何分派任务,可使总时间最少? 间如下表所示,问如何分派任务,可使总时间最少?
再看一例
请求解如下矩阵表达的指派问题
12 7 9 7 9 8 9 6 6 6 7 17 12 14 9 15 14 6 6 10 4 10 7 10 9
Байду номын сангаас
减去最小元素
5 0 2 0 2 2 3 0 0 0 0 10 5 7 2 9 8 0 0 10 0 6 3 6 5
√
调整可行解
7 4 0 11 0
0 2 0 3 0 0 8 3 5 8 0 0 4 1 4
2 0 0 10 3
第五章 匈牙利法与最佳指派问题
![第五章 匈牙利法与最佳指派问题](https://img.taocdn.com/s3/m/e9b386900c22590103029d03.png)
7 2 2
4
3
8 3 5 3
11 8
4
4 1 4
情况一出现,即得到了最优解,其相应的解矩阵为:
0 1 0 0 0
0 0 1 0 0
xij
1
0
0
0
0
0 0 0 1 0
0 0 0 0 1
由此得知最优指派方案为甲完成任务B,乙完成任务
C,丙完成任务A,丁完成任务D,戊完成任务E,最少时
间为
min z 7 6 7 6 6 32
而总的最少时间为32天.
当然,由于方法中的第二步4中的情况二的出现,造成 指派问题的最优解常常是不唯一的,但不同最优解的 最优值总是相同的.
第三节 非标准指派问题
前一节的匈牙利法只适用于目标函数为极小、价值 系数矩阵为方阵且价值系数矩阵中元素均为非负的情况。 当指派问题不满足上述三个条件时,就应先化成标准的 指派问题,然后再用匈牙利法求解.
解:
ABC DEF
甲 16 10 12 15 0 0 8 2
甲 16 10 12 15 0 0
8
2
乙 11 12 10 18 0 0 3 2 3
乙
11
12
10
18
0
0
3
2
3
丙 8 17 13 16 0 0 7 3 1
丙
8
17 13 16
0
0
7
3
1
8 10 10 15
本例经过反复的行、列检验后得到如下矩阵:
5 2 2
2
3
10 5 7 5
9
8
4
6 3 6 2
情况三出现,亦即未得到完全分配方案,求解过程 按以下步骤继续进行。
匈牙利法的指派问题-33页文档资料
![匈牙利法的指派问题-33页文档资料](https://img.taocdn.com/s3/m/6135f6535fbfc77da369b16a.png)
C
c11 c21
ci1
b
c12 c22
ci2 b
cn1
cn2
c1n c2n
cin b
cnn
minZ Z b
minZ Zb
若X0是minZ的最优, 解则 X0也是 minZ的最优解
指派问题的最优解:
若C中有n 个位于不同行不同列的零元素,
则令这些零元素对应的变量取1,其余变量
例:有一份说明书要分别译成英、 工作
日、德、俄四种文字,现交给甲、人
英日德 俄
乙丙、丁四个人去完成,每人完 甲 2 15 13 4
成一种。由于个人的专长不同,
乙 丙
10 4 14 15 9 14 16 13
翻译成不同文字所需的时间(小 丁 7 8 11 9
时数)如右表,问应派哪个人去
完成哪个任务,可使总花费时间
2
C
10
9 7
15 4 14 8
13 14 16 11
4 -2
15 -4
13 9
-9 -7
0
6 0 0
13 0 5 1
11 10 7 4
2 0 13
11
4 2
6
0 0
0 5 1
7 6 3 0
0
9
2
0
-4 -2
最优解的取法:
从含0元素最少的行或列开始,圈出一个0元 素,用 ○表示,然后划去该○所在的行和列 中的其余0元素,用×表示,依次类推,若能 得到n个○,则得最优解X0
最 优
取x14 1,x22 1, x31 1, x43 1 ,其余 xij 0
解
总费用 Z c14 x14 c22x22c31x31c43x43 0
运筹学指派问题的匈牙利法
![运筹学指派问题的匈牙利法](https://img.taocdn.com/s3/m/f6e9c309561252d380eb6e66.png)
运筹学课程设计指派问题的匈牙利法专业:姓名:学号: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件工作。
指派问题匈牙利算法最大值
![指派问题匈牙利算法最大值](https://img.taocdn.com/s3/m/1904a1dc18e8b8f67c1cfad6195f312b3169ebe8.png)
指派问题匈牙利算法最大值
匈牙利算法(匈牙利算法,也被称为“插入-删除算法”或“排序算法”)是一种整数排序算法,在指派问题中可以将一个整数数组按照一定规则排序,使得所有指派中最大的元素出现的位置都不相同。
以下是匈牙利算法在解决指派问题的最大值问题的步骤:
1. 将数组分为两个部分,左半部分尽可能地小,右半部分尽可能地大。
2. 从右半部分开始,将一个元素与它的指派对象的最大值进行
比较。
如果两个元素之间的指派关系不符合要求,就将它们交换位置。
3. 接下来,从左边半部分开始,将一个元素与它的指派对象的最大值进行比较。
如果两个元素之间的指派关系不符合要求,就将它们交换位置。
4. 重复步骤2和步骤3,直到左半部分的最大值与右半部分的最大值相等。
5. 在最右半部分找到最大的元素,将它与左半部分的最大值交换。
6. 重复步骤1到步骤5,直到数组中的所有元素都被排序。
匈牙利算法的时间复杂度为O(nlogn),其中n为数组的长度。
在实际应用中,该算法通常用于小规模数据的排序,对于大规模数据的
排序则需要使用更高效的算法。
匈牙利法解决人数与任务数不等的指派问题1
![匈牙利法解决人数与任务数不等的指派问题1](https://img.taocdn.com/s3/m/2fab002f482fb4daa58d4bfb.png)
匈牙利法解决人数与任务数不等的指派问题于凯重庆科技学院经济管理学院物流专业重庆沙坪坝区摘要:本文将讨论运筹学中的指派问题,而且属于非标准指派问题,即人数与任务数不相等的指派问题,应当视为一个多目标决策问题,首先要求指派给个人任务数目两两之间相差不能超过1,其次要求所需总时间最少,并且给出了该类问题的求解方法。
关键词:运筹学指派问题匈牙利算法系数矩阵解矩阵引言:在日常的生产生活中常遇到这样的问题:有n项任务,有n个人员可以去承担这n 项任务,但由于每位人员的特点与专长不同,各对象完成各项任务所用的时间费用或效益不同;有因任务性质要求和管理上需要等原因,每项任务只能由一个人员承担来完成,这就涉及到应该指派哪个人员去完成哪项任务,才能使完成n项任务花费总时间最短,总费用最少,产生的总效益最佳。
我们把这类最优匹配问题称为指派问题或分配问题。
1.指派问题的解法——匈牙利法早在1955年库恩(w.w.ku.hn)就提出了指派问题的解法,该方法是以匈牙利数学家康尼格(koning)提出的一个关于矩阵中0元素的定理为基础,因此得名匈牙利法(The Hungonrian Method of Assignment)1.1匈牙利解法的基本原理和解题思路直观的讲,求指派问题的最优方案就是要在n阶系数矩阵中找出n个分布于不用行不同列的元素使得他们的和最小。
而指派问题的最优解又有这样的性质:若从系数矩阵C(ij)的一行(列)各元素都减去该行(列)的最小元素,得到新矩阵CB(ij),那么以CB(ij)为系数矩阵求得的最优解和原系数矩阵C(ij)求得的最优解相同。
由于经过初等变换得到的新矩阵CB(ij)中每行(列)的最小元素均为“○”,因此求原指派问题C(ij)的最优方案就等于在新矩阵CB(ij)中找出n个分布于不同行不同列的“○”元素(简称为“独立○元素”),这些独立○元素就是CB(ij)的最优解,同时与其对应的原系数矩阵的最优解。
匈牙利法解决人数及任务数不等的指派问题
![匈牙利法解决人数及任务数不等的指派问题](https://img.taocdn.com/s3/m/621d9c5443323968001c9255.png)
匈牙利法解决人数与任务数不等的指派问题于凯重庆科技学院经济管理学院物流专业重庆沙坪坝区摘要:本文将讨论运筹学中的指派问题,而且属于非标准指派问题,即人数与任务数不相等的指派问题,应当视为一个多目标决策问题,首先要求指派给个人任务数目两两之间相差不能超过1,其次要求所需总时间最少,并且给出了该类问题的求解方法。
关键词:运筹学指派问题匈牙利算法系数矩阵解矩阵引言:在日常的生产生活中常遇到这样的问题:有n项任务,有n个人员可以去承担这n 项任务,但由于每位人员的特点与专长不同,各对象完成各项任务所用的时间费用或效益不同;有因任务性质要求和管理上需要等原因,每项任务只能由一个人员承担来完成,这就涉及到应该指派哪个人员去完成哪项任务,才能使完成n项任务花费总时间最短,总费用最少,产生的总效益最佳。
我们把这类最优匹配问题称为指派问题或分配问题。
1.指派问题的解法——匈牙利法早在1955年库恩(,该方法是以匈牙利数学家康尼格(koning)提出的一个关于矩阵中0元素的定理为基础,因此得名匈牙利法(The Hungonrian Method of Assignment)1.1匈牙利解法的基本原理和解题思路直观的讲,求指派问题的最优方案就是要在n阶系数矩阵中找出n个分布于不用行不同列的元素使得他们的和最小。
而指派问题的最优解又有这样的性质:若从系数矩阵C(ij)的一行(列)各元素都减去该行(列)的最小元素,得到新矩阵CB(ij),那么以CB(ij)为系数矩阵求得的最优解和原系数矩阵C(ij)求得的最优解相同。
由于经过初等变换得到的新矩阵CB(ij)中每行(列)的最小元素均为“○”,因此求原指派问题C(ij)的最优方案就等于在新矩阵CB(ij)中找出n个分布于不同行不同列的“○”元素(简称为“独立○元素”),这些独立○元素就是CB(ij)的最优解,同时与其对应的原系数矩阵的最优解。
1.2匈牙利法的具体步骤第一步:使指派问题的系数矩阵经过变换在各行各列中都出现○元素。
指派问题与匈牙利解法
![指派问题与匈牙利解法](https://img.taocdn.com/s3/m/0fff9c5632687e21af45b307e87101f69e31fb93.png)
指派问题与匈⽛利解法指派问题概述:实际中,会遇到这样的问题,有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线。
第五讲 分配问题(指派问题)与匈牙利法
![第五讲 分配问题(指派问题)与匈牙利法](https://img.taocdn.com/s3/m/d059d07a31b765ce0508144e.png)
n 件工作
y1 , y2 , … , yn 。 已 知 工 人 xi 完 成 工 作 yj 所 需 时 间 为 cij
分派方案满足下述两个条件: 分派方案满足下述两个条件:
1.任一个工人都不能去做两件或两件以上的工作 1.任一个工人都不能去做两件或两件以上的工作 2.任一件工作都不能同时接受两个及以上的工人去做 2.任一件工作都不能同时接受两个及以上的工人去做
min
4 7 6 6 6
8 7 15 12 4 0 4 3 11 8 0 3 0 11 8 9 17 14 10 7 0 2 10 7 3 0 1 7 7 3 9 12 8 7 6 ⇒ 0 3 6 2 1 ⇒ 0 2 3 2 1 7 14 6 10 6 0 1 8 0 4 0 0 5 0 4 0 3 6 4 0 0 2 3 4 0 9 12 10 6 6 min 0 1 3 0 0
5 0 2 0 2 3 0 0 0 10 5 7 9 8 0 0 0 6 3 6
9 8 5 4 0
尝试对所有零元素做标记,确定独立零元素。 尝试对所有零元素做标记,确定独立零元素。 标记 独立零元素
(2)逐列检验 )
与行检验类似:对只有一个未标记的零元素的列 用记号O将该 与行检验类似:对只有一个未标记的零元素的列,用记号 将该 零元素圈起,然后将被圈起的零元素所在行 零元素圈起,然后将被圈起的零元素所在行的其他未标记的零元 素用记号/划去 划去。 素用记号 划去。 重复列检验,直到没有未被标记的零元素或至少有两个未被标记 没有未被标记的零元素 重复列检验,直到没有未被标记的零元素或 的零元素为止。 的零元素为止。
分配问题(指派问题) 第5讲 分配问题(指派问题)与匈牙利法
指派问题的匈牙利法ppt
![指派问题的匈牙利法ppt](https://img.taocdn.com/s3/m/ceb6f545fd4ffe4733687e21af45b307e971f969.png)
确定调整行与列
在没有圈起得零所在行上打“√”; 在打“√”行中所有零所在得列打“√”; 在打“√”列中含有圈起零得行上打“√”, 反复执行2)与3)两步,直到不能打“√”为止; 用直线划去打“√”得列与不打“√”得行,没有
划去得行构成调整得行,划去得列构成调整列。
调整可行解得方法
在调整行中寻找最小得元素,将它作为调整 量;
将调整行各元素减去调整量,对调整列中各 元素加上调整量。
再次执行“圈零”与“划零”得操作,并循 环以上得步骤,直到圈起得零数等于n为止。
匈牙利法解例3、3
时间矩阵
2 10 3 7
15
4
14
8
13 14 16 11
4
7
13
任务
人员
A
B
C
D
甲
6
7
11
2
乙
4
5
9
8
丙
3
1
10
4
丁
5
9
8
2
求解过程如下:
第一步,变换系数矩阵:
6 7 11 2 2
(cij
)
4 3
5 1
9 10
8 4 4 1
5 9 8 2 2
4 5 9 0 0 1 5 4 2 0 9 3 3 7 6 0
4 5 4 0 0 1 0 4 2 0 4 3 3 7 1 0
0元素,就以这n个独立0元素对应解矩阵(xij)中得元素为1, 其余为0,这就得到最优解。找独立0元素,常用得步骤为:
(1)从只有一个0元素得行(列)开始,给这个0元素加圈, 记作◎ 。然后划去◎ 所在列(行)得其它0元素,记作Ø ; 这表示这列所代表得任务已指派完,不必再考虑别人了。
指派问题——匈牙利法共34页文档
![指派问题——匈牙利法共34页文档](https://img.taocdn.com/s3/m/79b49528f7ec4afe04a1dfd0.png)
42、只有在人群中间,才能认识自 己。——德国
43、重复别人所说的话,只需要教育; 而要挑战别人所说的话,则需要头脑。—— 玛丽·佩蒂博恩·普尔
44、卓越的人一大优点是:在不利与艰 难的遭遇里百折不饶。——贝多芬
45、自己的饭量自己知道。——苏联
指派问题——匈牙利法
36、如果我们国家的法律中只有某种 神灵, 而不是 殚精竭 虑将神 灵揉进 宪法, 总体上 来说, 法律就 会更好 。—— 马克·吐 温 37、纲纪废弃之日,便是暴政兴起之 时。— —威·皮 物特
38、若是没有公众舆论的支持,法律 是丝毫 没有力 量的。 ——菲 力普斯 39、一个判例造出另一个判例,它们 迅速累 聚,进 而变成 法律。 ——朱 尼厄斯
指派问题例题
![指派问题例题](https://img.taocdn.com/s3/m/77350d6fb80d6c85ec3a87c24028915f804d84d2.png)
• 第四步 划线——无行、打列划线
• 第五步 造0——直线未覆盖旳元素,减
去其最小值,交叉点上加最小元素,产
生新旳0元素,Go to 2
0 6 2 1 -1 5 1 0 0 4 0
Cij= 0 5 3 1 -1 0 4 2 0 3 1 0
0001
1 0 1
2 0 2
1320
2 3 2 2 2 1
数模: minZ=ΣΣcijxij Σxij=1 i=1,…,n Σxij=1 j=1,…,n Xij=0或1
任务 人 时间
甲 乙 丙 丁
ABC D 4 10 7 5 2763 3344 4663
指派问题解法—匈牙利法
• 解:类似运送问题旳最小元素法
• 第一步 造0——各行各列减其最小元素
4 10 7 5 -4 0 6 3 1 6 2 1
+1
• 最优2 7 6 3 -2 0 5 4 1 0 5 3 1
3 3 4 4 -3 0 0 1 1 0 0 1
4 6 6 3 -3 1 3 3 0 1 3 2
-1
• 第二步 圈0——寻找不同行不同列旳0元素,
圈之。 所在行和列其他0元素划掉
• 第三步 打——无旳行打,打行上0列打
,打列上行打,打行上0列打 …
指派问题
任务 人 时间
甲 乙 丙 丁
ABC D 4 10 7 5 2763 3344 4663
最大流问题
v1
5,2
5,5 5,5
vs 6,4 v2
4,2
v4 6,6
v3
2,2
4,2 vt
5,3
指派问题——匈牙利法
• 练习例题:甲乙丙丁四个人,A、B、C、D 四项任务,不同旳人做不同旳工作效率不同, 表中数据为时耗,怎样指派不同旳人去做不 同旳工作使效率最高?
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
11 10 7 4
2 0 13
11
4 2
6
0 0
0 5 1
70
-4 -2
最优解的取法:
从含0元素最少的行或列开始,圈出一个0元 素,用 ○表示,然后划去该○所在的行和列 中的其余0元素,用×表示,依次类推,若能 得到n个○,则得最优解X0
13 7 06 53 10
90 02
可行解
j1 i1
xi1 xi2 xi3 xi4 1 i=1,2, 3,4 s.tx1jx2jx3jx4j 1j=1,2, 3,4
xij 0 ,1i 1 ,2 ,3 ,4 ;j 1 ,2 ,3 ,4
最 优
取x14 1,x22 1, x31 1, x43 1 ,其余 xij 0
英日德 俄
乙丙、丁四个人去完成,每人完 甲 2 15 13 4
成一种。由于个人的专长不同,
乙 丙
10 4 14 15 9 14 16 13
翻译成不同文字所需的时间(小 丁 7 8 11 9
时数)如右表,问应派哪个人去
完成哪个任务,可使总花费时间
最少?
C最总优17920费方1184用45案111:16431:211丙94甲853 小翻翻----2497时译译 英俄 0060 文文11503 ,,11-74014乙丁-12翻2421翻 译译日德0060 文文11503
c12
c22
cn2
ccc12nnnn 0
cij表示第i个人做第j件事的费用
费用矩阵
3、匈牙利法
定理:在费用矩阵C=(cij)的任一行(列)中 减去一个常数或加上一个常数不改变本 问题的最优解。
C
c11 c 21
c i1
c12 c 22
ci2
c1n c2n
c in
-b
c n1
cn2
c nn
b m c i1 i ,c i n 2 , ,c i n
C
c11 c21
ci1
b
c12 c22
ci2 b
c1n c2n
cin b
cn1
3.4 0-1整数规划 三、指派问题与匈牙利法
矩阵的概念
矩阵的引入 某班级同学早餐情况
姓名 馒头 包子 鸡蛋 稀饭
周星 4
2
驰
2
1
张曼 0
0
玉
0
0
陈水 4
9
扁
8
6
为了方便,常用下面右边的数表表示
4 2 2 1
0 4
0 9
0 8
0 6
这个数表反应了学生的早餐情况
1、指派问题的数学模型
设有n个工作,要由 n个人来承 担,每个工作只能由一个人承 担,且每个人只能承担一个工 作。cij表示第i个人做第j件事 的费用,求总费用最低的指派 方案。
解:
x ij
1
0
第i个人做第j 人件事 第i个人不做第j 人件事
i=1,2, …,n; j=1,2, …,n
Z表示总费用
12…j …n
7 6 3 0
0
9
2 0
?
最优x解 141, x22 1, x31 1, x43 1 ,其余 xij 0
2
C
10
9 7
15 4 14 8
13 14 16 11
4 -2 15 -4
13 9
-9 -7
0
6
0 0
13 0 5 1
xi1 xi2 j ixij xin 1
s.tx1jx2j xjii==j 11 ,,22,, ……x,n ,nn j1
xij0 ,1i 1 ,2 , ,n ;j 1 ,2 , ,n
2、费用矩阵
设有n个工作,要由 n个人来承 担,每个工作只能由一个人承 担,且每个人只能承担一个工 作。cij表示第i个人做第j件事 的费用,求总费用最低的指派 方案。
1 c11 c12 c1 j c1n 2 c 21 c 22 c 2 j c 2 n … i c i1 c i 2 c ij c in …
n c n1 c n 2 c nj c nn
指派问题模型:
miZ n
cijxij
解
总费用 Z c14 x14 c22x22c31x31c43x43 0
匈牙利法的基本思路:
对费用矩阵C的行和列减去某个常数,将C化成 有n 个位于不同行不同列的零元素,令这些零元 素对应的变量取1,其余变量取零,既得指派问 题的最优解
例:有一份说明书要分别译成英、 工作
日、德、俄四种文字,现交给甲、人
cn2 cnn
minZ Z b
minZ Zb
若X0是minZ的最优, 解则 X0也是 minZ的最优解
指派问题的最优解:
若C中有n 个位于不同行不同列的零元素,
则令这些零元素对应的变量取1,其余变量
取零,既得指派问题的最优解
44
minZ
cijxij
0
例如: C0060
12…j …n
1 c11 c12 c1 j c1n 2 c 21 c 22 c 2 j c 2 n … i c i1 c i 2 c ij c in … n c n1 c n 2 c nj c nn
取C ccc12n111
最优x解 141, x22 1, x31 1, x43 1 ,其余 xij 0
44
最优值 Z: cijxij c14 c22 c31 c43 28 j1 i1
例:求费用矩阵为右表的 指派问题的最优解
工作
人 甲 乙 丙 丁 戊
ABCDE
12 7 9 7 9 89 6 6 6 7 17 12 14 12 15 14 6 6 10 4 10 7 10 6
12
8
C
7
7 9 17
9 6 12
7 6 14
9 -7
6 -6
12
-7
5 2
0
0 3 10
2 0 5
0 0 7
2 0