数字化婚姻配对尝试问题(C++实现)

问题描述:
一、标题:

数字化婚姻配对尝试

二、题目:

建立一个模型,来模拟推导社会男女择偶过程。

为了模型简化,一个人的特性指标有三个,这里假设为财富、样貌、品格,每个指标均可取值1-100之间任意数字。同样也对这3项指标有自己的需求。这3个需求值取值范围都在1-98间,当然三者的和必须为100.所以任意一个人可以用以下数组来表述:

G(A、B、C、A1、B1、C1)G代表男,M代表女。

举例G11(80、50、40、10、30、60),表示男11号,拥有财富80、样貌50、品格40,对异性品格的偏好为:财富在乎程度百分之10、样貌在乎程度百分之30、品格在乎程度百分之60。

同样为了模型简化,假设信息是完全对称的,即是说,每个人都能一眼就能看清楚任意一个人的财富、样貌、品格。

还是为了模型简化,我建模所用样本为男女各100个,即男女人数相同。

每个人对异性的满意度将如下定义:每个偏好指标与异性的对应的禀赋指标相乘,三个指标的乘积再相加,即他(她)对某个异性的满意度。

举例G11(80、50、40、10、30、60)对M(50、60、80、40、10、50)的满意度为:

(10*50+30*60+60*80)= 7100分

相对的 MM 对 GG的满意度则为:

(40*80+10*50+50*40) = 5700分

好了,配对活动开始,设计的配对法则如下:

1、100个男方,顺序,轮流从0号到99号女方中挑选自己最满意的一位,然后向她发出配对邀请。

2、接受邀请最多的女方开始行动,对这些邀请的男性中,选择最满意的一位。

3、那么这两位配对成功,剔除出样本,剩下的99对继续这样配对。

4、循环该配对法则,直到最后一对男女配对成功。

在匹配时,如果发现有多个满意度相同的对象,要求自身三个属性(财富,外貌,品格)总和大的优先,如果再相同则id小的优先。如果有2位女士的选票相同,优先级规则同上。请把主角的id置为最小值,以便在前2个条件相同情况下,主角可以优先选择。

附件中,male.txt,female.txt,players.txt 分别是男士样本、女士样本和主角样本各 100位。 男女样本中,每行都代表一位男士或女士的基本属性,从左到右依次是ID, 样貌,品格,财富 , 期望样貌,期望品格,期望财富,没有加入性别,需要在解析时手动添加,每个txt文本的性别都是一样的,请注意。另外,主角样本中没有ID属性,换成了性别属性,其中 0表示女性,1表示男性,其余属性依次为样貌,品格,财富,期望样貌 ,期望品格,期望财富。建议把主角的id都设置为 -1,以便满足优先选择的条件。

设计思路:
1、设计一个个体基类(Person),其包含属性(ID, 样貌,品格,财富 , 期望样貌,期望品格,期望财富);

2、基类基础上派生出男士类(Male)、女士类(Female)和主角类(Players),主角类中需要增加属性性别(msex)并设计一个配对类(Pairing),该类中封装了此问题的核心配对操作;

3、从文件中依次读取数据,放入相应的vector容器中;

4、所有的男生向女生发出配对邀请;

5、找出收到邀请最多的男生,进行反配对选择;

6、输出配对结果。

代码实现:
#include<iostream>
#include<vector>
#include<iterator>
using namespace std;
//个体类
class Person
{
public:
//构造函数
Person(int id,int w,int f,int p,int pw,int pf,int pp):
mid(id)
,mwealth(w)
,mface(f)
,mpersonality(p)
,mper_wealth(pw)
,mper_face(pf)
,mper_personality(pp)
{}
int getid(){return mid;}
int getwealth(){return mwealth;}
int getface(){return mface;}
int getpersonality(){return mpersonality;}
int getper_wealth(){return mper_wealth;}
int getper_face(){return mper_face;}
int getper_personality(){return mper_personality;}
private:
int mid; //id
int mwealth; //财富
int mface; //样貌
int mpersonality; //品格
int mper_wealth; //需求财富
int mper_face; //需求样貌
int mper_personality;//需求品格
friend class Male;
friend class Female;
};

//男生类
class Male:public Person //派生类
{
public:
Male(int id,int w,int f,int p,int pw,int pf,int pp)
:Person(id,w,f,p,pw,pf,pp){}

//修改id
void setid(int id)
{
Person::mid = id;
}
private:
friend class Pairing; //声明友元类
};

//女生类
class Female:public Person //派生类
{
public:
//构造函数
Female(int id,int w,int f,int p,int pw,int pf,int pp)
:Person(id,w,f,p,pw,pf,pp){}

//修改id
void setId(int id)
{
Person::mid = id;
}
private:
vector<int> loveMaleId; //存储男生id,该男生对自己发送邀请
friend class Pairing;
};

//主角类
class Players:public Person
{
public:
Players(int id,int w,int f,int p,int pw,int pf,int pp,int sex)
:Person(id,w,f,p,pw,pf,pp),msex(sex){}

int getSex(){return msex;}

//类型转换函数 Players === > Female
Female makeFemale(Players &players)
{
Female female(players.getid(),players.getwealth(),players.getface(),players.getpersonality()
,players.getper_wealth(),players.getper_face(),players.getper_personality());
return female;
}

//类型转换函数 Players === > Male
Male makeMale(Players &players)
{
Male male(players.getid(),players.getwealth(),players.getface(),players.getpersonality()
,players.getper_wealth(),players.getper_face(),players.getper_personality());
return male;
}
private:
int msex; //表示性别
};

const int MAXPLAYERS = 100; //限定最大配对次数
class Pairing //配对类
{
public:
//初始化mmale
void filetommale()
{
char *path = "E:\\male.txt";
int id,w,f,p,pw,pf,pp;
FILE *fp = fopen(path,"r");
if(NULL == fp)
{
printf("Do not open the file\n");
exit(EXIT_FAILURE);
}
for(int i = 0;i < 100;i++)
{
fscanf(fp,"%d,%d,%d,%d,%d,%d,%d",&id,&w,&f,&p,&pw,&pf,&pp);
Male male(id,w,f,p,pw,pf,pp);
mmale.push_back(male);
}
fclose(fp);
}
//初始化female
void filetomfemale()
{
char *path = "E:\\female.txt";
int id,w,f,p,pw,pf,pp;
FILE *fp = fopen(path,"r");
if(NULL == fp)
{
printf("Do not open the file\n");
exit(EXIT_FAILURE);
}
for(int i = 0;i < 100;i++)
{
fscanf(fp,"%d,%d,%d,%d,%d,%d,%d",&id,&w,&f,&p,&pw,&pf,&pp);
Female female(id,w,f,p,pw,pf,pp);
mfemale.push_back(female);
}
fclose(fp);
}
//初始化players
void filetomplayers()
{
char *path = "E:\\players.txt";
int id,w,f,p,pw,pf,pp,sex;
FILE *fp = fopen(path,"r");
if(NULL == fp)
{
printf("Do not open the file\n");
exit(EXIT_FAILURE);
}
for(int i = 0;i < 100;i++)
{
fscanf(fp,"%d,%d,%d,%d,%d,%d,%d",&sex,&w,&f,&p,&pw,&pf,&pp);
Players players(-1,w,f,p,pw,pf,pp,sex);
mplayers.push_back(players);
}
fclose(fp);
}
//所有男生对女生发送邀请
void maletofemale(vector<Male> male,vector<Female>& female)
{
//外层循环,遍历男生
int i = 0;
auto it_male = male.begin();
for(;it_male != male.end();++it_male,i++)
{
//剔除配对失败的男生
if(it_male->getid() == -2){continue;}
int satisfaction = 0;//计算出满意度,并找出最心仪的
int maxSatisfaction = 0; //假定最心仪的
int index = 0; //记录最心仪女生在容器中的位置
//内层循环,找出该男生最心仪的女生,并向其发出邀请
int j = 0;
vector<Female>::iterator it_female = female.begin();
for(;it_female != mfemale.end();++it_female,j++)
{
//剔除配对失败的女生
if(it_female->getid() == -2){continue;}
satisfaction = it_male->getper_wealth() * it_female->getwealth()
+ it_male->getper_face() * it_female->getface()
+ it_male->getper_personality() * it_female->getpersonality();
if(satisfaction > maxSatisfaction) //满意度比较
{
maxSatisfaction = satisfaction;
index = j;
}
else if(satisfaction == maxSatisfaction) //满意度一样的话
{
int curSatisfactionNum = it_female->getwealth()
+ it_female->getface() + it_female->getpersonality();
int oldSatisfactionNum = female[index].getwealth()
+ female[index].getface() + female[index].getpersonality();
if(curSatisfactionNum > oldSatisfactionNum) //比较自身值
{
index = j;
}
else if(curSatisfactionNum == oldSatisfactionNum) //自身值一样
{
if(it_female->getid() < female[index].getid()) //比较id
{
index = j;
}
}
}
}
//将该男生id传入女生
female[index].loveMaleId.push_back(it_male->getid());
}
}
//找到邀请最多的女生
int inviteMax()
{
int maxPeople = 0; //表示收到最多邀请的个数
int femaleIndex = 0; //记录收到最多男生邀请的女生在容器中的位置
//遍历容器,找出那个女生收到男生的邀请最多
int i = 0;
vector<Female>::iterator it_female = mfemale.begin();
for(;it_female != mfemale.end();++it_female,i++)
{
if(it_female->loveMaleId.size() > maxPeople) //比较邀请人数
{
maxPeople = it_female->loveMaleId.size();
femaleIndex = i;
}
else if(it_female->loveMaleId.size() == maxPeople) //邀请人数一样
{
int curFemaleNum = it_female->getwealth() + it_female->getface() + it_female->getpersonality();
int oldFemaleNum = mfemale[femaleIndex].getwealth()
+ mfemale[femaleIndex].getface() + mfemale[femaleIndex].getpersonality();
if(curFemaleNum > oldFemaleNum) //比较自身值
{
femaleIndex = i;
}
else if(curFemaleNum == oldFemaleNum) //自身值一样
{
if(it_female->getid() < mfemale[femaleIndex].getid()) //比较id
{
femaleIndex = i;
}
}
}
}
return femaleIndex; //返回获取最多邀请的女生在容器中的位置
}

//女生挑选自己最心仪的一位男生,返回心意男生在容器中的位置
int femaleselectunique(vector<Female> &female)
{
//记录那个女生进行配对,注意idIndex表示配对女生在容器中的位置
int idIndex = inviteMax();

//此时已经知道那个女生收到的男生邀请是最多的
//接下来在这些男生中找到女生最心仪的一个男生

//遍历女生收到邀请的男生id,找出最心仪的一个
int satisfaction = 0; //表示满意程度
int maxSatisfaction = 0; //表示最满意的
int maleIndex = 0;
//外层循环向女生提出过邀请的男生
auto it1 = mfemale[idIndex].loveMaleId.begin();
for(;it1 != mfemale[idIndex].loveMaleId.end();++it1)
{
//内存循环找出对应男生id的全部信息
int j = 0;
vector<Male>::iterator it_male = mmale.begin();
for (;it_male != mmale.end();++it_male,++j)
{
if(it_male->getid() == *it1)
{
satisfaction = mfemale[idIndex].getper_wealth() * it_male->getwealth()
+ mfemale[idIndex].getper_face() * it_male->getface()
+ mfemale[idIndex].getper_personality() * it_male->getpersonality();
if(satisfaction > maxSatisfaction)
{
maxSatisfaction = satisfaction;
maleIndex = j;
}
else if(satisfaction == maxSatisfaction) //满意度比较
{
int curSatisfactionNum = it_male->getwealth() + it_male->getface() + it_male->getpersonality();
int oldSatisfactionNum = mmale[maleIndex].getwealth() + mmale[maleIndex].getface() + mmale[maleIndex].getpersonality();
if(curSatisfactionNum > oldSatisfactionNum) //自身比较
{
maleIndex = j;
}
else if(curSatisfactionNum == oldSatisfactionNum)
{
if(it_male->getid() < mmale[maleIndex].getid()) //id比较
{
maleIndex = j;
}
}
}
}
}
}
return maleIndex; //返回的是心仪男生最容器中的位置
}

//配对失败,将其余的男生重新分配到容器里-----仅仅是向配对失败女生发出过邀请的那一部分男生
void clearvector(vector<Female> &female,int mfemale)
{
vector<int> otherMaleId = female[mfemale].loveMaleId;
female[mfemale].loveMaleId.clear();
vector<Male> otherMale;
//外层循环其他男生
vector<int>::iterator it = otherMaleId.begin();
for(;it != otherMaleId.end();++it)
{
//内存循环找出对应男生的全部信息
vector<Male>::iterator it_male = mmale.begin();
int i = 0;
for(;it_male != mmale.end();++it_male,++i)
{
if(mmale[i].getid() == *it)
{
otherMale.push_back(mmale[i]); //将该男生对象插入
}
}
}
maletofemale(otherMale,female); //将剩余的男生重新分配
}
//输出配对情况
void show()
{
//获取主角数据
filetomplayers();
//定义一个计数器
int count = 0;

while(count < MAXPLAYERS)
{
filetommale(); //获取男生数据
filetomfemale(); //获取女生数据

//添加主角
if(mplayers[count].getSex(http://www.my516.com) == 0)
{
mfemale.push_back(mplayers[count].makeFemale(mplayers[count]));
}
else
{
mmale.push_back(mplayers[count].makeMale(mplayers[count]));
}

//此时已经将数据主角插入进去
//下面进行配对

//所有男生向女生发送邀请
maletofemale(mmale,mfemale);

int count_index = 0; //定义一个计数器
while(count_index < MAXPLAYERS)
{
//哪一个女生进行配对
int femaleId = inviteMax();
//女生选择自己最心仪的一个男生
int maleId = femaleselectunique(mfemale);
//检查是不是主角
if(mmale[maleId].getid() == -1 || mfemale[femaleId].getid() == -1)
{
cout<< "第" << count + 1 << "组player加入:" << mmale[maleId].getid() << ":" << mfemale[femaleId].getid() << endl;
break;
}
else
{
//修改男生id
mmale[maleId].setid(-2);
//修改女生id
mfemale[femaleId].setId(-2);
//去除选择该女生的男生
clearvector(mfemale,femaleId);
}
count_index++;
}
if(count_index == 100)
{
cout<< "第" << count + 1 << "组player加入:" << " " << ":" << " " << endl;
}
count++;
mmale.clear(); //清空
mfemale.clear(); //清空
}
}
private:
vector<Male> mmale;
vector<Female> mfemale;
vector<Players> mplayers;
};
int main()
{
Pairing a;
a.show();
return 0;
}
运行结果:
第1组player加入:-1:28
第2组player加入:33:-1
第3组player加入:4:-1
第4组player加入:11:-1
第5组player加入:46:-1
第6组player加入:65:-1
第7组player加入:-1:39
第8组player加入:-1:41
第9组player加入:49:-1
第10组player加入:-1:80
第11组player加入:-1:36
第12组player加入:-1:23
第13组player加入:-1:29
第14组player加入:-1:86
第15组player加入:36:-1
第16组player加入:-1:98
第17组player加入:-1:11
第18组player加入:-1:76
第19组player加入:20:-1
第20组player加入:-1:47
第21组player加入:-1:77
第22组player加入:41:-1
第23组player加入:-1:20
第24组player加入:57:-1
第25组player加入:-1:45
第26组player加入:-1:39
第27组player加入:-1:36
第28组player加入:-1:9
第29组player加入:-1:22
第30组player加入:79:-1
第31组player加入:-1:45
第32组player加入:-1:86
第33组player加入:22:-1
第34组player加入:-1:34
第35组player加入:45:-1
第36组player加入:97:-1
第37组player加入:67:-1
第38组player加入:-1:13
第39组player加入:-1:39
第40组player加入:-1:60
第41组player加入:-1:15
第42组player加入:56:-1
第43组player加入:-1:97
第44组player加入:26:-1
第45组player加入:71:-1
第46组player加入:-1:27
第47组player加入: :
第48组player加入:85:-1
第49组player加入:-1:97
第50组player加入:-1:46
第51组player加入:-1:49
第52组player加入:4:-1
第53组player加入:-1:35
第54组player加入:27:-1
第55组player加入:65:-1
第56组player加入:77:-1
第57组player加入:-1:73
第58组player加入:-1:94
第59组player加入:-1:83
第60组player加入:52:-1
第61组player加入:48:-1
第62组player加入:-1:53
第63组player加入:2:-1
第64组player加入:-1:12
第65组player加入:-1:78
第66组player加入:-1:84
第67组player加入:-1:69
第68组player加入:97:-1
第69组player加入:26:-1
第70组player加入:-1:97
第71组player加入:71:-1
第72组player加入:-1:78
第73组player加入:1:-1
第74组player加入:-1:28
第75组player加入:55:-1
第76组player加入:-1:28
第77组player加入:-1:10
第78组player加入:-1:81
第79组player加入:-1:87
第80组player加入:74:-1
第81组player加入:-1:63
第82组player加入:33:-1
第83组player加入: :
第84组player加入:79:-1
第85组player加入:66:-1
第86组player加入:9:-1
第87组player加入:66:-1
第88组player加入:-1:58
第89组player加入:37:-1
第90组player加入:14:-1
第91组player加入:-1:21
第92组player加入:54:-1
第93组player加入:-1:78
第94组player加入:77:-1
第95组player加入:78:-1
第96组player加入:-1:94
第97组player加入:53:-1
第98组player加入:-1:56
第99组player加入:-1:45
第100组player加入:14:-
---------------------

原文地址:https://www.cnblogs.com/ly570/p/11060564.html

时间: 2024-10-12 06:44:48

数字化婚姻配对尝试问题(C++实现)的相关文章

中兴捧月杯 数字配对

一.标题: 数字化婚姻配对尝试 二.题目: 建立一个模型,来模拟推导社会男女择偶过程. 为了模型简化,一个人的特性指标有三个,这里假设为财富.样貌.品格,每个指标均可取值1-100之间任意数字.同样也对这3项指标有自己的需求.这3个需求值取值范围都在1-98间,当然三者的和必须为100.所以任意一个人可以用以下数组来表述: G(A.B.C.A1.B1.C1)G代表男,M代表女. 举例G11(80.50.40.10.30.60),表示男11号,拥有财富80.样貌50.品格40,对异性品格的偏好为:

POJ3487[稳定婚姻]

The Stable Marriage Problem Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 2974 Accepted: 1267 Description The stable marriage problem consists of matching members of two different sets according to the member’s preferences for the other

稳定婚姻问题和Gale-Shapley算法(转)

什么是算法?每当有人问作者这样的问题时,他总会引用这个例子:假如你是一个媒人,有若干个单身男子登门求助,还有同样多的单身女子也前来征婚.如果你已经知道这些女孩儿在每个男孩儿心目中的排名,以及男孩儿们在每个女孩儿心中的排名,你应该怎样为他们牵线配对呢? 最好的配对方案当然是,每个人的另一半正好都是自己的“第一选择”.这虽然很完美,但绝大多数情况下都不可能实现.比方说,男1号最喜欢的是女1号,而女1号的最爱不是男1号,这两个人的最佳选择就不可能被同时满足.如果好几个男孩儿最喜欢的都是同一个女孩儿,这

婚姻算法笔记

婚姻算法 曾经有想过类似的问题,婚姻算法中是关于情侣,我想的也是关于情侣方面.当时的想法是:如果每个人都将自己喜欢的人排出个名次列出,供别人参考,不就少了很多失败的表白和示爱吗.男生可以看在女生的排名中的名次来决定追不追.但只想到这里就结束了,没有想过当工作集从单链变成环时应该如何让每个人幸福. 婚姻算法是由Gale和Shapley提出,不考虑版本是雇主和员工还是男女情侣,现在我们只讨论男女情侣,讨论另外一种也可以,其中包含的条件都是相似的.要在已知每个人喜好排名的情况下,安排出匹配.使得婚姻稳

【转】麻省理工告诉我们男女配对的真相

来源:财富加油站     作者:hefangfang     发布时间:2015-09-09 17:17:06http://www.caifujy.com/news/150909/1.html 该实验出自麻省理工学院著名经济学家Dan Ariely的<The Upside of Irrationality>.其结果很有趣,也在我们的生活中尤为常见. Part 1. 实验人员找来100位正值青春年华的大学生.男女各半.然后制作了100张卡片,卡片上写了从1到100总共一百个数字. 单数的50张卡

HDU 1522 Marriage is Stable 【稳定婚姻匹配】(模板题)

<题目链接> 题目大意: 给你N个男生和N个女生,并且给出所有男生和女生对其它所有异性的喜欢程度,喜欢程度越高的两个异性越容易配对,现在求出它们之间的稳定匹配. 解题分析: 稳定婚姻问题的模板题,需要用到Gale_Shapley算法,GS算法讲解  >>> 这个算法还是很直观的. 1 #include <iostream> 2 #include <cstring> 3 #include <stack> 4 #include <stri

Android蓝牙自动配对Demo,亲测好使!!!

蓝牙自动配对,即搜索到其它蓝牙设备之后直接进行配对,不需要弹出配对确认框或者密钥输入框. 转载请注明出处http://blog.csdn.net/qq_25827845/article/details/52400782 经过最近一段时间得研究,针对网上给出的案例.总结了一个亲测好使的Demo. 说明如下: 1.本Demo用来连接蓝牙设备HC-05,如果你要连接其他蓝牙设备,注意修改相关名字以及修改设备初试pin值. 2.将Demo安装在Android手机上,点击按钮,可以实现与目标蓝牙设备的自动

uva 1175 Ladies&#39; Choice (稳定婚姻问题)

uva 1175 Ladies' Choice Background Teenagers from the local high school have asked you to help them with the organization of next year?s Prom. The idea is to find a suitable date for everyone in the class in a fair and civilized way. So, they have or

(算法)稳定婚姻匹配

题目: 婚介所登记了N位男孩和N位女孩,每个男孩都对N个女孩的喜欢程度做了排序,每个女孩都对N个男孩的喜欢程度做了排序,你作为月老,能否给出稳定的牵手方案? 稳定的定义:如果男孩i和女孩a牵手,但男孩i对女孩b更喜欢,而女孩b的男朋友j拼不过男孩i,则没有力量阻碍男孩i和女孩b的私奔,这即是不稳定的. 思路: 1962 年,美国数学家 David Gale 和 Lloyd Shapley 发明了一种寻找稳定婚姻的策略.不管男女各有多少人,不管他们各自的偏好如何,应用这种策略后总能得到一个稳定的婚