婚姻匹配问题

1.问题分析

问题描述:有N男N女,每个人都按照他对异性的喜欢程度排名。现在需要写出一个算法安排这N个男的、N个女的结婚,要求两个人的婚姻应该是稳定的。何为稳定?有两对夫妻M1 F2,M2 F1。M1心目中更喜欢F1,但是他和F2结婚了,M2心目中更喜欢F2,但是命运却让他和F1结婚了,显然这样的婚姻是不稳定的,随时都可能发生M1和F1私奔或者M2和F2私奔的情况。所以在做出匹配选择的时候(也就是结婚的时候),我们需要做出稳定的选择,以防这种情况的发生。要求:boys和girls各自给出自己心仪的嘉宾的顺序,请编写程序求出一种稳定的匹配,使匹配结果不会发生私奔现象。

本题主要是争对从男性优先发出邀约选择,女士来接受或拒绝,匹配的结果对发出邀约方有利,即男性找到的配偶满意度高。

2.问题的解决方案/算法选择/设计思路

2-1.设计思路

每轮男生都要向自己心目中排名最高的女生追求(建立一个数组,数组值记录被追求女生过的排名到哪里了);分别为男女生建立一个二位数组[][j],j为心目之中的排名,其中值为女生号,即哪个女生;女生要存放自己的现男友是谁(建立一个数组,数组值记录女生现在的现男友),用来和追求者相比;男生要存放现女友是谁为了判断有没有男生是单身的(建立一个数组,数组值记录男生的现女友)如果值为0就没有女朋友。

2-2.详细步骤

在最开始输入需要配对的对数num;boyper[num][num]定义一个数组存放女生在男生心中的排位;girlper[num][num]定义一个数组存放男生在女生心中的排位;定义一个q确定数字是否在配对对数范围内;然后输入各个男生女生心目中另一半的排名q,如果q在范围内则带入数组j的位置。

定义一个数组来存放各男女的对象其中i为其对应数组位置,内容为其对象的号,也就是从一开始的号,所以初始化为0代表他们都没有对象;为了保证追求过的不再重复追求,男性渴望追求的偏好女性在不断更新,初始大家都为0 从偏好数组第一位开始 i为这个男生的对应数组位置,内容用于约会女生的对于位置。然后看看有没有男生存在没对象,如果有,按序号遍历所有男生看看谁没有,如果某男士没有对象,优先追求偏好高的女生(在心目中排名靠前的女生),存储当前男生还未追求的最高偏好女性的号即是哪个女生 (boychase),然后判断这个女生有没有现任,如果为boychasebf=0就是没男朋友为其他数字就是男朋友是哪个。如果女孩有现任,然后判断是否稳定,如果被追求女生更喜欢现任!则女孩继续和现任在一起,如果该男生比该男生准备追求的女士的现任在心目中更好,女孩现任变成单身,该男士的对象变成准备追求的女士,女士的对象变成该男士。如果女孩没有现任,女生和追求的男生在一起。然后boyml[i]++该男生的偏好移动,这个女生已经追过,继续循环。循环结束后输出最终结果,谁和谁最终在一起了。

其中有一个current_male_is_better函数,用来比较某女士现在的对象和追求者哪个在她心目中排行更高, 数组参数是一维(是一位女士的优先表而不是所有女士的优先表), rank_of_current, rank_of_chasing是现任排行与追求者排行,将这两者进行比较,如果rank_of_current < rank_of_chasing,则更偏好原对象,相反则更偏向追求者,更新追求者。

3.算法设计/问题求解中所遇到的问题及分析解决方案

一怎么证明算法可以在有限时间内结束?

因为每名男性只可能向特定的女性求婚一次。所以,总的求婚次数最多是n²,n就是男性或女性人数。这个数字是有限的,所以算法必然在有限时间内结束。

二怎么确定算法结束时,每个人都结婚了?

可以用反证法,如果有这种情况,那么存在一个女人,她从来未被求过婚,并且有从未向这个女人求过婚的男人。但这是不可能的,因为如果只剩下这个男人和这个女人没有结婚,那么根据算法,不管这个女人在这个男人的喜好列表里的排名有多低,他还是得向这个女人求婚。所以,算法结束时,所有人都结婚了。

三怎么证明所有婚姻是稳定的?

还是用反证法,如果存在这样两对不稳定夫妻,且不稳定因素是Bob和Alice。那么因为Alice在Bob心目中的排名比其现任妻子高,则Bob必然在现任妻子之前向Alice求婚过。而Alice心目中,Bob的排名比现任丈夫高,则不管其现任丈夫在Bob之前或之后求婚,留下的必然是Bob。所以不可能出现不稳定婚姻。

4. 代码:

#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];//定义一个数组存放男生在女生心中的排位

int q;//确定数字是否在配对对数范围内

for (int i = 0; i < num; i++){

printf("男生%d心中的女生排行:",i+1);

for (int j = 0; j < num; j++){

scanf("%d",&q);

if(q<=num&&q>0){

boyper[i][j]=q;

}else{

printf("输入错误,请重新输入");

j--;

}

}

}

for (int i = 0; i < num; i++){

printf("女生%d心中的男生排行:",i+1);

for (int j = 0; j < num; j++){

scanf("%d",&q);

if(q<=num&&q>0){

girlper[i][j]=q;

}else{

printf("输入错误,请重新输入");

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;//新追求者

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值