数字化婚姻配对尝试问题(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
#include
#include
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 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,vector& 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::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::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)
	{
		//记录那个女生进行配对,注意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::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,int mfemale)
	{
		vector otherMaleId = female[mfemale].loveMaleId;
		female[mfemale].loveMaleId.clear();     
		vector otherMale;
		//外层循环其他男生
		vector::iterator it = otherMaleId.begin();
		for(;it != otherMaleId.end();++it)
		{
			//内存循环找出对应男生的全部信息
			vector::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() == 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 mmale;
	vector mfemale;
	vector 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:-1

 

你可能感兴趣的:(数字化婚姻配对尝试问题(C++实现))