婚姻匹配问题
前言
盖尔-沙普利算法(Gale-Shapley)
简称“GS算法”,也称为延迟接受算法。是盖尔和沙普利为了寻找一个稳定匹配而设计出的市场机制。
一、问题描述
一共有N位男士和N位女士,每个人都要选择结婚对象。如果有两对夫妻M1 F2,M2 F1。M1心目中更喜欢F1,但是他和F2结婚了,M2心目中更喜欢F2,但是命运却让他和F1结婚了,显然这样的婚姻是不稳定的。根据个人对异性的排名情况匹配对象,使得每对情侣在结婚后婚姻状况稳定,从而保证不会出现出轨的状况。
二、算法思路
1.匹配模式
一个婚姻匹配M是一个包含n个(m, w)对的集合,每一对的成员都按照一对一的模式从两个不相交的n元素集合Y和X中选出。
也就是说, Y中的每个男士m都只和X中的一位女士w配对,反正亦然。如果在匹配M中,男士m和女士w没有匹配,但他们都更倾向对方,而不是M中彼此的伴侣,那么(m, w)称为受阻对,如果婚姻匹配存在受阻对,那么我们说婚姻是不稳定的,如果不存在,则婚姻是稳定的。
2.匹配流程
男女双方根据好感度排序:
1)第一轮
每个男士选择排名首位的女性并向她表白。
此时女士可能有三种情况:① 没有人向她表白;② 只有一个人向她表白 ③ 不止有一个人向她表白
在情况 ① 下,女士等待下一轮
在情况 ② 下,接受追求者表白,暂时达成恋爱关系
在情况 ③ 下,按照好感度排名选择追求者最,并暂时和他在一起
第一轮结束后,仍有男士单身。
2)第二轮
单身的男士从还没拒绝过自己的女士中按照好感度做出选择,不管她是否单身。
与第一轮相同,女士们需要选出自己最中意的那个,并达成恋爱关系。如果这个女士已经有男朋友了,当她遇到了更好的追求者时拒绝掉现在的男友,选择新的追求者。
此时,那些已经有了女友的人可能重新单身。
3)以后的每一轮
以第一、二轮为例,在以后的每一轮,单身男士继续追求其列表中的下一个女士,女士则从包括现男友在内的所有追求者中选择最好的一个。
这样一轮一轮的继续下去,直到某个时候所有人都不再单身,下一轮将不会再有新的表白发生。
三、关键代码
代码如下(示例):
int boyper[num][num];//定义一个数组存放女生在男生心中的排位
int girlper[num][num];//定义一个数组存放男生在女生心中的排位
for (int i = 0; i < num; i++){
printf("男生%d心中的女生排行:",i+1);
for (int j = 0; j < num; j++){
scanf("%d",&boyper[i][j]);
}
}
for (int i = 0; i < num; i++){
printf("女生%d心中的男生排行:",i+1);
for (int j = 0; j < num; j++){
scanf("%d",&girlper[i][j]);
}
}
while(finish_or_not(num, boygf)==false){//有男生存在没对象
for (int i=0;i<num;i++){//按序号遍历所有男生看看谁没有
if (boygf[i]==0){//如果某男士没有对象
printf("男生%d没有对象,可追求女生!\n",i+1);
//优先追求偏好高的女生
int boychase = boyper[i][boyml[i]];//存储当前男生还未追求的最高偏好女性的号即是哪个女生 (boychase)
//判断这个女生有没有现任
int boychasebf = girlbf[boychase-1];//存储当前追求的女士的对象(boychasebf)(号) 数组位置=号-1 (boychase-1)
printf("男生%d准备追偏好的女生%d\n",i+1,boychase);//i+1号
if (boychasebf!=0){//如果为0就是没男朋友为其他数字就是男朋友是哪个
printf("被追求女生的现任是%d\n", boychasebf);
//判断是否稳定
if (current_male_is_better(num, girlper[boychase-1],boychasebf, i+1)){ //数组,被追求的女性的偏好,当前对象,追求男的号
printf("被追求女生更喜欢现任!\n");//false
}
else{//如果该男生比该男生准备追求的女士的现任在心目中更好 ture
boygf[boychasebf-1]=0;//女孩现任变成单身
boygf[i] =boychase;//该男士的对象变成准备追求的女士
girlbf[boychase-1]=i+1;//女士的对象变成该男士
printf("男生%d横刀夺爱和女生%d在一起了!\n",i+1,boychase);
}
}
else{
printf("被追求的女生是单身\n");
boygf[i] =boychase;//该男士的对象变成准备追求的女士
girlbf[boychase-1]=i+1;//女士的对象变成该男士
printf("男生%d和女生%d在一起了!\n",i+1,boychase);
}
boyml[i]++;//该男生的偏好移动,这个女生已经追过
}
}
}
总结
在本次实验中,while循环和for嵌套,先插入了一个索引用来存放男性女性所对应各自心中的排名矩阵,然后从第一个位置开始逐个选取对象,并记录男士(女士)各自的选取过的索引,将未选取过的索引项即没有匹配的人放入队列中,以便于利用for循环进行遍历队列,在while循环中遍历索引,为男士选取未匹配的女士,否则便在女性中选取最优的男性与之配对,则男士也成为了未匹配人选,如此反复对比进行循环匹配。