婚姻匹配问题

目录

问题描述

解题思路

代码展示


问题描述

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值