稳定匹配(解决婚姻问题)
婚姻问题
现在有N位男生和N位女生,每个男生都对N个女生的喜欢程度做了排序,每个女生都对N个男生的喜欢程度做了排序,现在需要确定一个稳定的约会状态。
稳定的定义:如果男生i和女生a牵手,但男生i对女生b更喜欢,而女生b发现,相比自己的男朋友j,她更喜欢男生i,则没有力量阻碍男生i和女生b的私奔,这即是不稳定的。
解决思路
- 首先选择一个单身男生,他会按照他的喜欢程度对一个还没有表白过的女生表白。
- 如果女生此时处于单身状态,则恭喜,他们两人将进入约会状态。
- 如果女生已经有男朋友,则女生会比较当前男朋友与表白的男生,如果更喜欢表白的男生,则恭喜,男生成功上位,女生之间的男朋友则进入单身状态;若女生还是更喜欢自己的男朋友,则不好意思,男生表白失败。
- 当所有的男生都脱离单身状态时,此时的约会状态应是稳定的,证明如下。
若存在之前描述的不稳定因素,即虽然男生i和女生a牵手,但男生i对女生b更喜欢,而女生b发现,相比自己的男朋友j,她更喜欢男生i。既然男生i更喜欢女生b,那么男生i肯定在对女生b表白失败之后才会对女生a表白,而若男生i对女生b的表白失败,则女生b至少有比对男生i更喜欢的男朋友,所以女生b相比自己的男朋友j更喜欢男生i并不成立,所以此时所有的约会状态都是稳定的。
算法分析
首先构造People类,由其继承出来的有Man类和Woman类,它们都有的是setPrefer方法,设置自己的心爱对象排序列表。
Man类独有的是next方法,可以返回其心爱列表中最靠前的一个还没有表白过的心仪对象。
Woman类独有的是prefer方法,可以比较两个男生她更喜欢哪一个。
在存储结构上,可以分别选用两个数组存储所有的男生和女生,一个链表来存储所有单身的男生,一个数组来存储已有的配对情况。
主要算法步骤如下:
一. People类中有一个静态属性ID,会为每一个男生或女生赋予一个自增的ID,在创建男生或女生实例之前需要对其进行初始化。
二. 创建所有的男生和女生并设置其心爱顺序列表,初始化单身男生链表为所有男生,女生的男朋友数组每个元素都为空。
三. 当单身链表不为空则不终止循环。
四. 循环过程为:每次取一个单身的男生,将其从链表中删除,并给与其对还没有表白失败过的心仪女孩表白的权利。若其表白成功,则设置相应女生的男朋友为当前男生的ID,若相应女生之前的男朋友被绿,则将其男朋友插入到单身链表中;若其表白失败,则再将其插入到单身链表中。
源代码
测试数据为:
- 男生表:
男生\偏爱排序 | |||||
---|---|---|---|---|---|
Adam | Beth | Amy | Diane | Ellen | Cara |
Bill | Diane | Beth | Amy | Cara | Ellen |
Carl | Beth | Ellen | Cara | Diane | Amy |
Dan | Amy | Diane | Cara | Beth | Ellen |
Eric | Beth | Diane | Amy | Ellen | Cara |
- 女生表:
女生\偏爱排序 | |||||
---|---|---|---|---|---|
Amy | Eric | Adam | Bill | Dan | Carl |
Beth | Carl | Bill | Dan | Adam | Eric |
Cara | Bill | Carl | Dan | Eric | Adam |
Diane | Adam | Eric | Dan | Carl | Bill |
Ellen | Dan | Bill | Eric | Carl | Adam |
示例输出为:
Amy-Adam
Beth-Carl
Cara-Bill
Diane-Eric
Ellen-Dan
import java.util.ArrayList;
import java.util.LinkedList;public class Match {public static void main(String[] args) {ArrayList<Man> men;ArrayList<Woman> women;LinkedList<Man> menTmp;Integer[] current;People.init();Man Adam = new Man("Adam");Man Bill = new Man("Bill");Man Carl = new Man("Carl");Man Dan = new Man("Dan");Man Eric = new Man("Eric");People.init();Woman Amy = new Woman("Amy");Woman Beth = new Woman("Beth");Woman Cara = new Woman("Cara");Woman Diane = new Woman("Diane");Woman Ellen = new Woman("Ellen");men = new ArrayList<>();men.add(Adam.setPrefers(Beth, Amy, Diane, Ellen, Cara));men.add(Bill.setPrefers(Diane, Beth, Amy, Cara, Ellen));men.add(Carl.setPrefers(Beth, Ellen, Cara, Diane, Amy));men.add(Dan.setPrefers(Amy, Diane, Cara, Beth, Ellen));men.add(Eric.setPrefers(Beth, Diane, Amy, Ellen, Cara));women = new ArrayList<>();women.add(Amy.setPrefers(Eric, Adam, Bill, Dan, Carl));women.add(Beth.setPrefers(Carl, Bill, Dan, Adam, Eric));women.add(Cara.setPrefers(Bill, Carl, Dan, Eric, Adam));women.add(Diane.setPrefers(Adam, Eric, Dan, Carl, Bill));women.add(Ellen.setPrefers(Dan, Bill, Eric, Carl, Adam));menTmp = new LinkedList<>();for (Man m : men) {menTmp.push(m);}current = new Integer[men.size()];for (int i = 0; i < men.size(); i++) {current[i] = null;}while (!menTmp.isEmpty()) {Man man = menTmp.pop();int prefer = man.next();if (prefer != -1) {if (current[prefer] == null) {current[prefer] = man.getID();} else {if (women.get(prefer).prefer(current[prefer], man.getID())) {menTmp.push(men.get(current[prefer]));current[prefer] = man.getID();} else {menTmp.push(man);}}}}for (int i = 0; i < current.length; i++) {System.out.print(women.get(i));System.out.print("-");System.out.println(men.get(current[i]));}}
}class People {private String name;protected int ID;protected static int curID = 0;public static void init() {curID = 0;}public People(String name) {this.name = name;}public int getID() {return ID;}@Overridepublic String toString() {return name;}
}class Man extends People {private int[] prefers;private int index;public Man(String name) {super(name);this.ID = curID;curID++;}public Man setPrefers(Woman... women) {prefers = new int[women.length];for (int i = 0; i < women.length; i++) {prefers[i] = women[i].getID();}index = 0;return this;}public int next() {if (index < prefers.length) {return prefers[index++];} else {return -1;}}
}class Woman extends People {private int[] prefers;public Woman(String name) {super(name);this.ID = curID;curID++;}public Woman setPrefers(Man... men) {prefers = new int[men.length];for (int i = 0; i < men.length; i++) {prefers[men[i].getID()] = i;}return this;}public boolean prefer(int cur, int next) {return prefers[next] < prefers[cur];}
}
深入分析
首先这是一个男生向女生表白的思路,也即男生占主动位,女生占被动位。
虽然男生享有选择向不同女孩表白的权利,但是最终决定权在女方手中,即由女方决定是否接受男生的表白。而且,即使男生表白成功,也有被绿的可能,即当有女生更喜欢的男生向女生表白的时候,女生会毫不犹豫的抛弃他。
从大局来看,从一开始的不稳定约会,到最后的稳定婚姻的过程中,男生的伴侣总是从自己最喜欢的女生,慢慢地变成自己不怎么喜欢的女生,而女生的伴侣,却在一步步地变好,一步步地接近自己心目中的那个他。
所以这看起来好像是一个对女生有益的匹配策略。
但是更深入的分析之后,你会发现,虽然男生再一次次地被绿,但是他每次选择的女生都是有可能和他走到最后的女生中最好的一个,正是因为更好的女生会拒绝他的表白,所以最终和男生在一起的女生是可能和他在一起的女生中最好的一个。而对于女生来说,虽然她的男朋友在一步一步地变好,但是可能和她在一起的最好的那个男生,可能还没有轮到向她表白,就和他更喜欢的女生在一起了,所以并不能保证最终的伴侣是可能和她在一起的最好的那个男生。
所以这实际是一个对男生有益的匹配策略。同时也告诉了我们,努力争取总会比静心等待得来更好的结果。
以另一种思路思考哈,在N个可匹配对象中,如果你对最好的伴侣的期望值是N,对最差的期望值是1,以此类推,假设最终的匹配是你期望值为 N 2 \frac{N}{2} 2N的伴侣,令其中约会的持续时间平均为t,则男生所享受到的是: ∑ i = N 2 N i × t + N 2 × ∞ \sum_{i=\frac{N}{2}}^Ni×t+\frac{N}{2}×∞ ∑i=2NNi×t+2N×∞;而女生享受到的是: ∑ 1 N 2 i × t + N 2 × ∞ \sum_{1}^{\frac{N}{2}}i×t+\frac{N}{2}×∞ ∑12Ni×t+2N×∞
哈?懂不懂由你。
稳定匹配(解决婚姻问题)相关推荐
- 稳定匹配问题——稳定婚姻算法设计
图片源自:美剧<How I met your mother> **** 本代码带有详细的注释,并在控制台输出时详细地说明了算法的过程,非常有助于新手理解稳定匹配问题和稳定婚姻算法的设计思路 ...
- 稳定匹配婚姻 c++版GS算法
问题描述 给出一个 n 个男性的集合 M和 n 个女性的集合 W,找到一个"稳定"匹配. 每位男性根据对女性的心仪程度从高至低进行排名: 每位女性根据对男性的心仪程度从高至低进行排 ...
- 稳定匹配 5分钟看懂GS算法 附有常考常见例题及解析
文章目录 Stable Match 稳定匹配(GS算法) 1. 什么是稳定匹配 2. 为什么叫做稳定匹配 3. 稳定匹配的基本思想 4. 算法的伪代码 5. 为什么这个算法可以产生一个稳定的匹配? 1 ...
- 稳定伴侣问题c语言步骤,稳定匹配问题
这是 Algorithm Design 一书开篇介绍的一个很有意思的问题 问题描述 有n个男人和n个女人(n>=2),每个男人对所有女人有一个好感度排名,每个女人对所有男人也有一个好感度排名.将 ...
- 男女稳定匹配问题——贪心
今天上课研究生学长讲了一个问题,男女稳定匹配问题,作为一只单身狗觉得这个问题很有意思,下课就试着自己写了下代码. 现有n个男生与n个女生,一男一女配对,要求: 配对的男生与女生互相都是称心 ...
- 稳定匹配问题(脱单就靠这波了)
稳定匹配问题之三国 首先,我们先看看问题: 有n个男人和n个女人(n>=2),每个男人对所有女人有一个好感度排名,每个女人对所有男人也有一个好感度排名.将男女两两配对,得到n对男女,称之为一个完 ...
- c# “INSERT 语句中列的数目大于 VALUES 子句中指定的值的数目。VALUES 子句中值的数目必须与 INSERT 语句中指定的列的数目匹配解决方法
c# "INSERT 语句中列的数目大于 VALUES 子句中指定的值的数目.VALUES 子句中值的数目必须与 INSERT 语句中指定的列的数目匹配解决方法. 出错原因是SQL语句 VA ...
- 模板匹配 解决模板旋转以及重复检测问题
OpenCV Error: Assertion failed (scn == 3 || scn == 4)in cv::cvtColor, file C:\projects\opencv-python ...
- 与 vmx86 驱动程序的版本不匹配解决方法
一个新手可能遇到的问题 第一次安装完VMware后,启动时可能会遇到问题:与 vmx86 驱动程序的版本不匹配: 预期为xxx ,实际为 xxx. 驱动程序"vmx86.sys的版本不正确. ...
最新文章
- Zookeeper源码分析:主从角色关系流程概述
- 第三天学习Java的笔记(自增自减,赋值,比较,逻辑,三元)
- 并非最边界的情况“OK“就真的“OK“(记洛谷P1720WA的经历,Java语言描述)
- 聚合 aggregate
- 灯塔浮标行业调研报告 - 市场现状分析与发展前景预测(2021-2027年)
- tensorflow sigmoid 如何计算训练数据的正确率_初探 TensorFlow.js
- html 日期区间选择器,element日期范围选择器
- C/C++函数库 之 ctype.h
- local class incompatible: stream classdesc serialVersionUID = -3129896799942729832, local class seri
- java swing tooltips_tooltips 提示
- echarts地图 自定义区域
- 基于RGB颜色空间的算法
- 【技术网站分享】全面整理了一波技术网站,分享给大家!
- 蓝牙协议栈(六、芯片组)
- 诗:《假如生活欺骗了你》
- 日志系统新贵 Loki,确实比笨重的ELK轻
- 洗礼灵魂,修炼python(74)--全栈项目实战篇(2)——前期准备之详解虚拟机下安装ubuntu,基本配置,远程访问...
- ccie 与 java,Java和ccie的区别
- CSS outline:none;是什么意思???
- 来,跟我一起 ,自研多端错误监控平台(完整版)
热门文章
- 安全日志:/var/log/secure(转载 https://www.cnblogs.com/pzk7788/p/10184740.html)
- 12306 订票助手 1.3
- 当群星游戏打开显示无法访问Documents库的解决方案
- 2020年T电梯修理考试APP及T电梯修理证考试
- 《人月神话》-外科手术队伍
- 要么承受自律的苦,要么承担自责的悔。
- c++ dynamic_cast,static_cast,const_cast,reinterpret_cast四种cast用法整理
- 健康管理的营利模式及体系构建
- [R语言] 10行代码展示我国35个主要城市近一年来居民消费价格指数的变化
- 石头科技: 决胜百亿扫地机器人“价值高地”