大名鼎鼎的稳定婚姻算法
这个问题是我学到的比较有趣的算法问题前几名了,也是当年我们ACM校队面向新生宣讲的时候选择的例题。我们觉得用找对象这种新生会比较感兴趣的问题来忽悠他们,他们上钩的可能性比较大XD。
问题描述
婚姻匹配也可以叫做CP匹配,问题的场景非常简单。我们模拟真实的婚恋匹配的场景,比如线下的N男 vs N女的相亲活动。很自然的,男生和女生都会对异性在心里有一个评价,觉得自己中意哪个讨厌哪个,会有一个优先级排名。
我们要做的事情就是设计一个算法,将这N男和N女组成稳定的CP。因为如果是随便组CP的话非常简单,随便配对就好了,但是随便组成的CP并不一定和谐,很有可能不稳定,我们希望情侣们能够快乐地生活在一起。
解释一下稳定这个概念,我们假设男生有两个,男1和男2,女生也有两个女1和女2。假设我们组成的CP是男1和女2,男2和女1,但是呢,在女生当中,男1更喜欢女1,同样在男生当中女1也更喜欢男1。
也就是说和自己的对象相比,他们对彼此的喜欢要大于各自的伴侣。那么这种情况的CP就是不稳定的,时间长了有可能会出问题。为了简化问题模型,我们假设一定会出问题,男1最终会和女1在一起,他们各自和自己现在的CP”分手“。
我们希望能够把N男和N女组成CP,并且希望他们都不会分手,也就是说整个局面是稳定的。
问题的解法
关于这个问题,可能大家会有很多种想法,比如有些人会觉得应该给每个男生和女生根据受对方欢迎的情况打一个分。看看谁是被许多女生喜爱的优质男生,谁又是受男生欢迎的优质女生。
因为优质男生和优质女生受到对方的关注比较多,所以先把他们安排好,防止他们出现不稳定的情况。之后再去安排那些相对不那么受欢迎的男女生。
这种方法看似可以,但是实现起来非常复杂,可行性不高,因为优质男女之间以及优质男女和非优质男女之间都有可能出现不稳定的情况。本质上关于避免不稳定情况出现的逻辑还是欠缺的。
我们还可以用搜索算法来解,这个搜索空间其实是明确的,就是男女生配对,我们就是要搜索出一个稳定的配对情况。我们也可以用搜索问题来做,搜索出所有的可能,然后一个一个筛选,找到其中稳定的解。
这种方法当然是可以的,但是复杂度非常高,因为我们绝大多数的搜索情况是无效的。
有没有效率既高又可以充分解决问题的方法呢?
当然也是有的,并且还非常简单,就是让这些男生根据自己心中的排名去追求女生。那么就会出现多个男生同时或者先后追求同一名女生的情况,这里我们做一个非常简单的假设,假设女生始终会选择在自己列表上排名高的那一个男生作为自己的CP。
第一轮我们让所有的男生都去追求自己最心仪的女生,经过一系列竞争,必然会有一些男生成功的组成了CP。第二轮,我们让单身的男生再去追求自己第二喜欢的女生,经过一轮竞争,又有一些人脱单了。我们如此循环往复,直到所有的人都配对。
这样,我们的算法就介绍完了。
就这么简单吗?是的就这么简单,但是这样能保证所有男女都能找到对象吗?会不会有一些男女和女生剩下,或者是会出现不稳定的情况呢?
其实是不会的,证明也非常容易。
首先,可以证明不会出现有人没有配对成功的情况。我们假设存在一男一女最后落单的情况,那么假设的前提就是剩男已经向所有的女生都表过白并且被拒绝了。但女生在只有一个追求者的情况下是不会拒绝的,所以这就与假设矛盾了。所以算法不会出现没有结果的情况,可以保证所有男女都组成CP。
其次,我们可以证明不会出现男女不稳定的情况。我们也可以使用反证法,我们假设存在男1和女1彼此都是各自更加喜欢的,但是又没有在一起。但是根据我们算法的规则,那么男1必然先于当前的对象追求女1。那么对于女1来说,如果男1大于她当前的对象,她不可能不和男1在一起,所以这也是矛盾的。
到这里,整个算法的过程就介绍完了。这个算法其实是有来头的,并不是我们自己YY的,它的学名叫做Gale-Shapley算法。顾名思义是由Gale和Shapley两个人在1962年共同研究发表的,据说在该算法发表的10年之前,美国一些地方就使用这个算法来给医学院的毕业生分配工作。可见在很早之前,人们就意识到了稳定匹配的重要性,并且依据直觉开始应用了。
算法实现
这个算法其实很容易实现,我们只需要记录下面男生和女生当前的匹配情况,以及男生向女生发起追求的轮次,中间的逻辑非常简单。
女生如果单身,那么一定接受男生的追求,否则比较一下和现在对象的优先级。如果优先级更高,后来的男生竞争上岗,前面的男生下岗,回到单身状态。我们只需要把这些状态厘清,代码实现非常简单。我实现了一个版本,给大家提供一下参考:
import random
import sys# 生产测试数据,生成男生和女生心中的对象排序
def generate_list(n):base = list(range(n))random.shuffle(base)return baseif __name__ == "__main__":boys, girls = [], []n = int(sys.argv[1])for i in range(n):boys.append(generate_list(n))girls.append(generate_list(n))print('The preference of boys')print(boys)print('The preference of girls')print(girls)# 一开始的时候匹配状态记为-1girls_matched = [-1 for _ in range(n)]# 男生发起轮次记为0,表示下一次追求第几偏好的女生boys_round = [0 for _ in range(n)]boys_matched = [-1 for _ in range(n)]while True:all_matched = Truefor i in range(n):# 如果已经匹配了,则跳过if boys_matched[i] != -1:continueall_matched = Falsegirl = boys[i][boys_round[i]]boys_round[i] += 1# 如果女生没有对象,直接答应if girls_matched[girl] == -1:girls_matched[girl] = iboys_matched[i] = girlelse:# 否则和现在对象比较一下顺序idx = girls[girl].index(i)mate = girls_matched[girl]mate_idx = girls[girl].index(mate)if idx < mate_idx:boys_matched[i] = girlboys_matched[mate] = -1girls_matched[girl] = iif all_matched:breakprint('The match result of boys:')print(boys_matched)print('The match result of girls:')print(girls_matched)
我们运行一下代码,查看结果:
我们可以模拟一下,第一轮结果是[0-3], [1-4], [3-0], [4-2]。其中2和3号男生都向0号女生发起追求,0号女生接受了3号拒绝了2号。于是第二轮2号男生向2号女生发起追求,由于2号女已经和最佳心仪对象4号男组成了CP,所以2号男失败。继续向3号女发起追求,3号女的原来对象是0号男,由于0号男排名非常低,于是0号男被甩。所以第二轮的结果是[1-4],[2-3],[3-0],[4-2]。
第二轮的结果是0号男落下,0号男向4号以及0号女发起追求都宣告失败,最终和1号女组成CP。所有的男女都组成了CP,并且没有不稳定的情况出现。我们人工推理得到的结果和我们程序给出的结果完全一致。
总结
这个算法并不难,但是胜在非常有趣。实际上在生活当中有许多分配方案直接或者是间接使用了Gale-Shapley算法。如果大家熟悉算法的话,会发现其实这个问题的本质是二分图匹配。我们可以用二分图匹配的算法来解决这个问题。
如果我们研究一下这个算法的核心逻辑,会发现其实是对男生有优势的,虽然女生看起来有最终的选择权,但男生更有机会追求自己最心仪的对象,而女生只能被动地等待男生发起追求来进行挑选。如果某个女生喜欢的男生不选她,那么她永远没有和他在一起的机会。这个故事告诉我们,喜欢的对象要自己挑,主动才是王道。
如果你还单身的话,希望对你有所帮助。
大名鼎鼎的稳定婚姻算法相关推荐
- 稳定匹配问题——稳定婚姻算法设计
图片源自:美剧<How I met your mother> **** 本代码带有详细的注释,并在控制台输出时详细地说明了算法的过程,非常有助于新手理解稳定匹配问题和稳定婚姻算法的设计思路 ...
- “稳定婚姻算法”雨夜谈-M/N资源匹配问题
连续数月的阴雨绵绵,江南烟雨似乎没有停止的迹象,近日又迎来了下半年目前为止最猛烈的寒潮,无论哪一个都是我超级期待和喜欢的,这样的天气,不适合睡觉. 一个很不错的算法,稳定婚姻算法. 先给出一个概念,来 ...
- 稳定婚姻问题:Gale–Shapley算法
(一)问题的引出 在组合数学.经济学.计算机科学中,稳定婚姻问题(英语:stable marriage problem,简称SMP)又称为稳定配对问题(stable matching problem) ...
- 【文末福利】图论算法:稳定婚姻问题,如何找到最适合自己的另一半
什么是算法? >>>> 每当有人问我这样的问题,我总会引用下面这个例子. 假如你是一个媒人,有若干名单身男子登门求助,还有同样多的单身 女子也来征婚.如果你已经知道这些女孩儿在 ...
- 图论 —— 稳定婚姻问题与延迟认可算法
[稳定婚姻问题] 1.集合 M 表示 n 个男性 2.集合 F 表示 n 个女性 3.对于每个人我们都按异性的中意程度给出一份名单(从最中意的到最不中意的) 如果没有 ,f 对 m 比对她的配偶中意的 ...
- hdu - 1435 Stable Match 稳定婚姻问题、Gale-Shapley算法模板
稳定婚姻的描述: 假如你是一个媒人,有若干个单身男子登门求助,还有同样多的单身女子也前来征婚.如果你已经知道这些女孩儿在每个男孩儿心目中的排名,以及男孩儿们在每个女孩儿心中的排名,你应该怎样为他们牵线 ...
- ALG1:GS算法,稳定婚姻匹配问题
ALG1:GS算法,稳定婚姻匹配问题 问题描述如下: (详见NKU计算机上机课程辅助评测) 稳定婚姻匹配 实现代码: (此代码逻辑可通过全部测试样例) 由于代码有一段时间了,一下的展示代码是没有自己的 ...
- hdu1435 稳定婚姻问题
题意: Stable Match Special Judge Problem Description Network 公司的BOSS 说现在他们公司建立的信号发射站和接收站经常出现信号发送接收不稳定的 ...
- hdu1914 稳定婚姻问题
稳定婚姻问题就是给你n个男的,n个女的,然后给你每个男生中女生的排名,和女生心目中男生的排名,然后让你匹配成n对,使婚姻稳定,假如a和b匹配,c和d匹配,如果a认为d比b好,同时 ...
最新文章
- 难以置信的目标检测小妙招:多训练几个epochs,平均一下就能获得更好的模型...
- MathType如何保存常用公式
- 制作 OpenStack Linux 镜像 - 每天5分钟玩转 OpenStack(151)
- php 1天,自学PHP之第1天-字符串函数 - 晓雨网
- mysql8 安装_mysql 8.x 安装向导
- 让Dapper在一个项目中支持多种库
- mysql error 1449_MySql错误:ERROR 1449 (HY000)
- 微课|中学生可以这样学Python(例7.2):三维向量类
- 程序员学习资料(2)—硅谷之火,Html Css,python,mysql 等
- sip 接听后没有声音
- 扩散方程——热传导问题(能量定律+傅里叶热传导定律)+ 拉普拉斯方程 | 偏微分方程(三)
- 怎样将iphone照片通过MAC导入移动硬盘?
- matlab编写的程序输入参数怎么写,MATLAB|标准参数输入对话框创建
- Maven POM介绍
- XMAN misc writeup
- LINUX IIO子系统分析之二 IIO子系统相关数据结构分析
- Golang 同步等待组(WaitGroup)
- 【MATLAB】绘制矢量场图
- 【DSP】EPWM寄存器
- Mybatis 报The error occurred while handling results
热门文章
- matlab 线圈 互感,任意空间位置线圈的互感计算方法.PDF
- 计算机专业可以进水利高级职称,水利工程师评审副高需要什么条件?
- python 机器人工具箱——robotics-toolbox-python
- 【IDEA】IDEA相关
- 世界国家省份城市县区街道村地址邮编常用通用功能最全API - 多级联动 - 淘宝天猫阿里巴巴技术赏析...
- linux模拟驾驶软件下载,3D模拟驾考游戏
- Educoder - Java类和对象之对象组合之求圆柱体积
- 英语口语296之每日十句口语
- sqlalchemy.exc.NoSuchModuleError: Can‘t load plugin: sqlalchemy.dialects:mysql.p ymyql报错
- 阿里云千亿营收背后,一个新生态正蓬勃发展