目录
问题描述
有N男N女,每个人都按照他对异性的喜欢程度排名。现在需要写出一个算法安排这N个男的、N个女的结婚,要求两个人的婚姻应该是稳定的。何为稳定?有两对夫妻M1 F2,M2 F1。M1心目中更喜欢F1,但是他和F2结婚了,M2心目中更喜欢F2,但是命运却让他和F1结婚了,显然这样的婚姻是不稳定的,随时都可能发生M1和F1私奔或者M2和F2私奔的情况。所以在做出匹配选择的时候(也就是结婚的时候),我们需要做出稳定的选择,以防这种情况的发生。
要求:boys和girls各自给出自己心仪的嘉宾的顺序,请编写程序求出一种稳定的匹配,使匹配结果不会发生私奔现象。
解题思路
以图中10人配对为例
开始现在都处于未配对状态,男12345分别向自己最喜欢的女孩儿表白分别为CADAA。
1和C配对。3和D配对。A同时收到245的表白,根据自己好感度选择了5,5和A配对
第二轮
男生2和4单身,分别向第二好感女生B C表白。2和B配对成功。C已有男朋友1,比较1和4好感度,选择4,1恢复单身。
第三轮
男1单身,向第二好感女生B表白。B已有男友2,比对2和1好感度,选择2。1没有表白成功
第四轮
男1单身,向第三好感女生E表白成功
对于N人来说
首轮男生向第一好感度女生表白,若女生只有一位男性追求者直接配对成功,若有多位追求者则根据好感最高进行选择,配对成功。未成功男性向第二好感度女生表白(不管是否有男友);情况一:女生没有男友,接收追求者,配对成功。情况二,有男友,对比两位男性好感度。可能选择追求者,同时现任恢复单身,此时这位男士向第二好感女生表白。可能选择现任,追求者被拒绝,他向下一高好感度女生表白。
代码展示
#include<stdio.h>
#include<iostream>
bool finish_or_not(int, int *);
bool current_male_is_better(int num, int *girlper, int current, int chasing);
int main(){
int num=0;int i,j;
printf("请输入需要配对的对数:");
scanf("%d",&num);
if(num==0)
{
printf("没有人数无法匹配,请重新输入匹配对数:");
scanf("%d",&num);
}
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]);
}
}
//定义一个数组来存放各男女的对象其中i为其对应数组位置,内容为其对象的号,也就是从一开始的号,所以初始化为0代表他们都没有对象
int *girlbf = new int[num];//
int *boygf = new int[num];
for (int i = 0; i < num; i++){
girlbf[i] = 0;
boygf[i] = 0;
}//现任
//为了保证追求过的不再重复追求,男性渴望追求的偏好女性在不断更新
int *boyml= new int[num];
for (int i = 0; i < num; i++){
boyml[i] = 0;//初始大家都为0 从偏好数组第一位开始 i为这个男生的对应数组位置,内容用于约会女生的对于位置
}
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]++;//该男生的偏好移动,这个女生已经追过
}
}
}
for (int i=0; i<num;i++){
printf("男生%d和女生%d最后走到一起 \n",i+1,boygf[i]);
}
}
bool finish_or_not(int num, int *boygf){
for (int i=0; i<num;i++){
if (boygf[i]==0){//判断是否全部完成配对
printf("有可配对的单身人士");
return false;
}
}
printf("全部配对完成\n");
return true;
}
//比较某女士现在的对象和追求者哪个在她心目中排行更高
//数组参数是一维(是一位女士的优先表而不是所有女士的优先表)
bool current_male_is_better(int num, int *girlper, int current, int chasing){ //数组,被追求的女性的偏好,当前原来对象,追求男的号
int rank_of_current, rank_of_chasing;//现任排行与追求者排行
for (int i = 0; i < num; i++){
if (girlper[i]==current){
rank_of_current = i+1;//位数
}
if (girlper[i]==chasing){
rank_of_chasing = i+1;
}
}
printf("在女士心目中现任排名是: %d,而追求者排名则是: %d\n",rank_of_current,rank_of_chasing);
if (rank_of_current < rank_of_chasing)
return true;//更偏好原对象
else
return false;//新追求者
}