稳定婚姻匹配问题
一、问题
有N男N女,每个人都按照他对异性的喜欢程度排名。现在需要写出一个算法安排这N个男的、N个女的结婚,要求两个人的婚姻应该是稳定的。
何为稳定?
有两对夫妻M1 F2,M2 F1。M1心目中更喜欢F1,但是他和F2结婚了,M2心目中更喜欢F2,但是命运却让他和F1结婚了,显然这样的婚姻是不稳定的,
随时都可能发生M1和F1私奔或者M2和F2私奔的情况。所以在做出匹配选择的时候(也就是结婚的时候),我们需要做出稳定的选择,以防这种情况的发生。
二、算法步骤描述:
第一轮,每个男人都选择自己名单上排在首位的女人,并向她表白。这种时候会出现两种情况:
(1)该女士还没有被男生追求过,则该女士接受该男生的请求。
(2)若该女生已经接受过其他男生的追求,那么该女生会将该男士与她的现任男友进行比较,若更喜欢她的男友,那么拒绝这个人的追求,否则,抛弃其男友(囧)……
第一轮结束后,有些男人已经有女朋友了,有些男人仍然是单身。
在第二轮追女行动中,每个单身男都从所有还没拒绝过他的女孩中选出自己最中意的那一个,并向她表白,不管她现在是否是单身。这种时候还是会遇到上面所说的两种情况,还是同样的解决方案。直到所有人都不在是单身。
三、基于hdu1522题的模板与讲解
#include <iostream> #include <cstring> #include <stack> #include <map> using namespace std; int n,gp_boy[505][505],gp_girl[505][505],boy[505],girl[505],rank[505]; map<string,int>mp_boy,mp_girl; string sboy[505],sgirl[505]; char s[1000]; void Gale_Shapley() { memset(boy,0,sizeof(boy));///假设所有人是单身狗 memset(girl,0,sizeof(girl)); for(int i=1;i<=n;i++) rank[i]=1; while(1) { int flag=0; for(int i=1;i<=n;i++)///男生们开始追女生 { if(!boy[i])///如果男生是单身狗 { int g=gp_boy[i][rank[i]++];///开始最第一喜欢的女生 if(!girl[g])///如果女生恰好没有对象 { boy[i]=g;///在一起~ girl[g]=i; } else if(gp_girl[g][i]>gp_girl[g][girl[g]])///如果女孩孩子有对象但是比起对象更稀罕这个男生 { boy[girl[g]]=0;///原来的甩掉!! girl[g]=i; boy[i]=g; } flag=1; } } if(!flag) break; } for(int i=1;i<=n;i++) { cout<<sboy[i]<<" "<<sgirl[boy[i]]<<endl; } } int main() { while(cin>>n)///n个男 n个女 { mp_boy.clear();///清空 mp_girl.clear(); int pos=1,tem; for(int i=1;i<=n;i++)///n个男生 { cin>>s; sboy[i]=s;///i号男生对应的名字 mp_boy[s]=i;///名字是s的男生对应的序号 for(int j=1;j<=n;j++) { cin>>s; ///男生喜欢的女生排名 tem=mp_girl[s];///看女生s的序号 if(tem==0)///如果序号是0 mp_girl[s]=tem=pos++;///给人家女孩子一个序号 sgirl[tem]=s;///序号tem的女生是s gp_boy[i][j]=tem;///所以第i号男生第j喜欢的女生的序号是tem } } for(int i=0;i<n;i++)///这时的我们看看女孩子喜欢的男生 { cin>>s; int x=mp_girl[s];///get到s女孩子的序号 for(int j=0;j<n;j++) { cin>>s; int y=mp_boy[s];///get到女孩第j个喜欢男孩子的序号 gp_girl[x][y]=n-j;///所以第x号女生喜欢y号男生的程度为n-j } } Gale_Shapley(); } return 0; }
你若是天才,我便是疯子