稳定婚姻问题

15 篇文章 0 订阅

题目大意:
现在有n个男士,n个女士,他们要组合家庭
每一个男士都对每一位女士有一个喜好值,同样每一个女士对每一个男士也有一个喜好值
现在要求一种组合方式,让婚姻稳定!
怎样才能稳定呢??如果存在一个男士和一位女士,他们不是夫妻,但是对对方的喜好度都大于现在的伴侣,那么这个婚姻是不稳定的,容易理解吧
那么怎样才能使婚姻稳定呢??
这个是数学界切切实实研究过的问题,而且现在有了好多的应用,下面介绍一下算法的实现,然后分析一个很有意思的结论“
下面就是求婚了
        第一天上午, 所有的男人都向自己最爱的女人求婚.下午, 每个女人看看自己有没有收到, 收到了多少人的求婚. 如果只收到一个男人的求婚, 那么就和他订婚. 如果收到多于一个男人的求婚, 那么就和其中她最爱的那个男人订婚, 同时把其他男人都锯掉. 如果一个求婚都没有, 不要着急, 最后总会有的.晚上, 检查一遍, 如果所有女人都订婚了, OK, 万事大吉, 明天举行集体婚礼.但如果还有女人没有订婚, 那么事情还没有完, 第二天还得重复.第二天上午, 所有还没订婚的男人向自己次爱的女人求婚(因为昨天已经被他们的最爱锯了).下午, 每个女人再看一遍自己收到订婚的情况. 如果她已经订婚了, 但是又有一个她更爱的男人来向她求婚, 那就把原来那个锯掉, 再和这个更爱的男人订婚; 如果还没订婚, 那就和第一天的下午的处理一样.晚上再检查一遍, 如果还是有人没有订婚, 那第三天再重复.第三天上午, 所有没有订婚的男人, 包括第一天订了第二天又被踹出来的, 再向还没有锯过他的女人中他最爱的那个求婚
...
如此周而复始, 直到最后大家都订了婚, 便一起结婚.

上面的算法就可以求出一个稳定的婚姻了,下面介绍几个数学上证明的结论:

第一, 这个过程会中止, 也就是说, 总有大家都订了婚的一天,不可能无限循环.
第二, 中止后所有的婚姻是稳定婚姻。
第三, 比较引人注目的是, 这个过程是male-optimal的, 男性能够获得尽可能好的伴侣, 比如说最后有二十个女人拒绝了他,他仍然能够得到剩下的八十个女人中他最爱的那一个.
第四, 更有甚者, 这个过程是female-pessimal的, 女人总是在可能的情况下被最不喜欢的人追上. 这一点没有那么直观的理解, 勉强要解释的话, 可以这么看: 虽说女人每换一次订婚对象, 都往上升一层, 但起点可能很低, 虽说在一步步接近她最爱的目标, 但最后往往达不到. 比如说还差三十名就达到她最爱的人了, 但这时Game Over, 所有的人都已订了婚, 这样她也只能死了心了. 还有三十个她更爱的人还没向她求过婚,可是她也无可奈何了...

哈哈,上面的第二和第三点很有意思,原来是这样啊。女同志不要愤怒哈,这个是数学上证明了的,当然这个只是个数学模型,但是挺好玩的,可能有人会问,数学家就那么无聊么?研究这样的问题??其实这个问题现在确实有着很多的应用,很多的资料都这么说的。
    ps:不管男生还是女生,如果遇到喜欢的,那就赶紧表白吧,即使被拒了,你还是可以找到一个相对较适合你的,被动的话可能可能有更好的机会你错过了。哈哈,纯属个人观点,!欢迎拍砖……
另:附上poj 3487代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
using namespace std;

#define N 27
int libman[N][N],man[N],ladyscore[N][N],lady[N];
int main()
{
    int cas,n,a[N];
    stack<int> freeman;
    string list;
    char temp;
    cin>>cas;
    while(cas--)
    {
        while(!freeman.empty())  freeman.pop();
        cin>>n;

        for(int i=0; i<n; i++)
        {
            cin>>temp;
            a[i]=temp-'a';
            freeman.push(a[i]);
        }
        sort(a,a+n);
        for(int i=0; i<n; i++)  cin>>temp;

        for(int i=0; i<n; i++)
        {
            cin>>list;
            for(int j=0; j<n; j++)
                libman[i][j]=list[j+2]-'A';
        }
        for(int i=0; i<n; i++)
        {
            cin>>list;
            for(int j=0; j<n; j++)
                ladyscore[i][list[j+2]-'a']=n-j;
        }

        for(int i=0; i<n; i++)
            ladyscore[i][n]=0;//对"不存在"的男生打最低分 这个是??

        memset(man,0,sizeof(man));
        for(int i=0; i<N; i++)  lady[i]=n; //这里不能用memset()因为n是变量而不是常数

        int male,female;

        while(!freeman.empty())
        {
            male=freeman.top();
            female=libman[male][man[male]];
            if(ladyscore[female][male]>ladyscore[female][lady[female]])
            {
                freeman.pop();
                if(lady[female]!=n)
                {
                    freeman.push(lady[female]);
                    man[lady[female]]++;
                }
                lady[female]=male;
            }
            else if(ladyscore[female][male]<ladyscore[female][lady[female]])
                man[male]++;
        }
        for(int i=0; i<n; i++)
            printf("%c %c\n",a[i]+'a',libman[a[i]][man[a[i]]]+'A');
        if(cas != 0) printf("\n");
    }
    return 0;
}




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值