數字化婚姻配對嘗試

建立一個模型,來模擬推導社會男女擇偶過程。

爲了模型簡化,一個人的特性指標有三個,這裏假設爲財富、樣貌、品格,每個指標均可取值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、循環該配對法則,直到最後一對男女配對成功。


ps:在匹配時,如果發現有多個滿意度相同的對象,要求自身三個屬性(財富,外貌,品格)總和大的優先,如果再相同則id小的優先。如果有2位女士的選票相同,優先級規則同上。請把主角的id置爲最小值,以便在前2個條件相同情況下,主角可以優先選擇。

male.txt,female.txt,players.txt 分別是男士樣本、女士樣本和主角樣本各 100位。 男女樣本中,每行都代表一位男士或女士的基本屬性,從左到右依次是ID, 樣貌,品格,財富 , 期望樣貌,期望品格,期望財富,沒有加入性別,需要在解析時手動添加,每個txt文本的性別都是一樣的,請注意。另外,主角樣本中沒有ID屬性,換成了性別屬性,其中 0表示女性,1表示男性,其餘屬性依次爲樣貌,品格,財富,期望樣貌 ,期望品格,期望財富。建議把主角的id都設置爲 -1,以便滿足優先選擇的條件。


#include <iostream>
#include <assert.h>
#include<vector>
#include<iterator>
using namespace std;

class Person
{
public:
	Person(int id,int a,int b,int c,int d,int e,int f)
		:mid(id),ma(a),mb(b),mc(c),md(d),me(e),mf(f){}

	int mid;
	int ma,mb,mc,md,me,mf;
};

class Male;
class Female:public Person
{
public:
	Female(int id,int a,int b,int c,int d,int e,int f)
		:Person(id,a,b,c,d,e,f){}

	void addInvite(int maleid)
	{
		maleId.push_back(maleid);
	}
	int matchMale(vector<Male> &maleVec);
	vector<int>& getmaleId()
	{
		return maleId;
	}
private:
	vector<int> maleId;
	friend class Male;
};

class Male:public Person
{
public:
	Male(int id,int a,int b,int c,int d,int e,int f)
		:Person(id,a,b,c,d,e,f){}
	void sendInvite(vector<Female> &femaleVec,int index)
	{
		femaleVec[index].addInvite(mid); 
	}
};

int Female::matchMale(vector<Male> &maleVec)
{
	int satisfaction = 0;
	int satisfaction_cur = 0;
	int index = 0;

	for (vector<int>::iterator id_it = maleId.begin();id_it != maleId.end();++id_it)
	{
		int j = 0;
		for (vector<Male>::iterator male_it = maleVec.begin();male_it != maleVec.end();++male_it,j++)
		{
			if (maleVec[j].mid == *id_it)
			{
				satisfaction_cur = md * maleVec[j].ma + me * maleVec[j].mb + mf * maleVec[j].mc;
				if (satisfaction_cur > satisfaction )
				{
					satisfaction = satisfaction_cur;
					index = j;
				}
				else if(satisfaction_cur == satisfaction )
				{
					int synthesize_cur = maleVec[j].ma + maleVec[j].mb + maleVec[j].mc;
					int synthesize_old = maleVec[index].ma + maleVec[index].mb + maleVec[index].mc;
					if (synthesize_cur > synthesize_old)
					{
						index = j;
					}
					else if (synthesize_cur == synthesize_old)
					{
						if (maleVec[j].mid < maleVec[index].mid)
						{
							index = j;
						}
					}
				}
			}

		}

	}
	return index;
}

class Player:public Person
{
public:
	Player(int id,int a,int b,int c,int d,int e,int f,int sex)
		:Person(id,a,b,c,d,e,f),msex(sex){}
	int getSex()
	{ 
		return msex;
	}
	Female makeFemale()
	{
		Female female(mid,ma,mb,mc,md,me,mf);
		return female;
	}
	Male makeMale()
	{
		Male male(mid,ma,mb,mc,md,me,mf);
		return male;
	}
private:
	//0 female //1 male
	int msex;
};

class CMatch
{
public:
	void loadMalesdata()
	{
		int id,a,b,c,d,e,f;
		FILE *fp = fopen("d:\\male.txt","r");
		assert(fp != NULL);

		for (int i=0;i<100;++i)
		{
			fscanf(fp,"%d,%d,%d,%d,%d,%d,%d",&id,&a,&b,&c,&d,&e,&f);
			Male male(id,a,b,c,d,e,f);
			maleVec.push_back(male);
		}
		fclose(fp);
	}
	void loadFemalesdata()
	{
		int id,a,b,c,d,e,f;
		FILE *fp = fopen("d:\\female.txt","r");
		assert(fp != NULL);

		for (int i=0;i<100;++i)
		{
			fscanf(fp,"%d,%d,%d,%d,%d,%d,%d",&id,&a,&b,&c,&d,&e,&f);
			Female female(id,a,b,c,d,e,f);
			femaleVec.push_back(female);
		}
		fclose(fp);
	}
	void loadPlayersdata()
	{
		int sex,a,b,c,d,e,f;
		FILE *fp = fopen("d:\\players.txt","r");
		assert(fp != NULL);

		for (int i=0;i<100;++i)
		{
			fscanf(fp,"%d,%d,%d,%d,%d,%d,%d",&sex,&a,&b,&c,&d,&e,&f);
			Player player(-1,a,b,c,d,e,f,sex);
			playerVec.push_back(player);
		}
		fclose(fp);
	}

	void maleCalculate(vector<Male> &maleVec)
	{
		int satisfaction = 0;
		int satisfaction_cur = 0;
		int index = 0;//記錄被邀請女性的索引

		int male_index=0;
		for (vector<Male>::iterator male_it = maleVec.begin();male_it != maleVec.end();++male_it,male_index++)
		{
			satisfaction = 0;
			satisfaction_cur = 0;
			index = 0;//記錄被邀請女性的索引

			if (male_it->mid == -2)
			{
				continue;
			}

			int i=0;
			for (vector<Female>::iterator female_it = femaleVec.begin();female_it != femaleVec.end();++female_it,i++)
			{
				if (female_it->mid == -2)
				{
					continue;
				}
				satisfaction_cur = male_it->md * female_it->ma + male_it->me * female_it->mb + male_it->mf * female_it->mc;
				if (satisfaction_cur > satisfaction )
				{
					satisfaction = satisfaction_cur;
					index = i;
				}
				else if(satisfaction_cur == satisfaction )
				{
					int synthesize_cur = female_it->ma + female_it->mb + female_it->mc;
					int synthesize_old= femaleVec[index].ma + femaleVec[index].mb + femaleVec[index].mc;
					if (synthesize_cur > synthesize_old)
					{
						index = i;
					}
					else if (synthesize_cur == synthesize_old)
					{
						if (female_it->mid < femaleVec[index].mid)
						{
							index = i;
						}
					}
				}
			}
			maleVec[male_index].sendInvite(femaleVec,index);
		}
	}
	void failmaleCalculate(int f_index)
	{
		vector<int> fail_idVec = femaleVec[f_index].getmaleId();
		femaleVec[f_index].getmaleId().clear();
		vector<Male> fail_maleVec;
		for (vector<int>::iterator id_it = fail_idVec.begin();id_it != fail_idVec.end();++id_it)
		{
			int j = 0;
			for (vector<Male>::iterator male_it = maleVec.begin();male_it != maleVec.end();++male_it,j++)
			{
				if (maleVec[j].mid == *id_it)
				{
					fail_maleVec.push_back(maleVec[j]);
				}
			}
		}
		maleCalculate(fail_maleVec);
	}

	int inviteMax()
	{
		int index = 0;
		int len = 0;
		int len_cur = 0;
		int i = 0;
		for (vector<Female>::iterator female_it = femaleVec.begin();female_it != femaleVec.end();++female_it,i++)
		{
			len_cur = femaleVec[i].getmaleId().size();
			if (len_cur > len )
			{
				len = len_cur;
				index = i;
			}
			else if (len_cur == len)
			{
				int synthesize_cur = femaleVec[i].ma+femaleVec[i].mb+femaleVec[i].mc;
				int synthesize_old = femaleVec[index].ma+femaleVec[index].mb+femaleVec[index].mc;
				if (synthesize_cur > synthesize_old  )
				{
					index = i;
				}
				else if (synthesize_cur == synthesize_old )
				{
					if (femaleVec[i].mid < femaleVec[index].mid)
					{
						index = i;
					}
				}
			}
		}
		return index;
	}

	void beginMatch()
	{
		loadPlayersdata();
		int index = 0;
		while (index < 100)
		{
			loadFemalesdata();
			loadMalesdata();

			if (playerVec[index].getSex() == 0)
			{
				femaleVec.push_back(playerVec[index].makeFemale());
			}
			else
			{
				maleVec.push_back(playerVec[index].makeMale());
			}
	
			//所有男向女發送邀請
			maleCalculate(maleVec);

			//最多選擇女性選擇一個男性
			int count = 0;
			while(count < 100)
			{
				int f_index = inviteMax();
				int m_index = femaleVec[f_index].matchMale(maleVec);

				//男女是否爲主角
				if (femaleVec[f_index].mid == -1  || maleVec[m_index].mid == -1)
				{
					cout<<"第"<<index+1<<"組player加入:"<<maleVec[m_index].mid<<":"<<femaleVec[f_index].mid<<endl;
					break;
				}
				else
				{
					//cout<<maleVec[m_index].mid<<":"<<femaleVec[f_index].mid<<endl;
					femaleVec[f_index].mid = -2;
					maleVec[m_index].mid = -2;
					//配對失敗的其他男性重新選擇
					failmaleCalculate(f_index);
				}
				count++;
			}
			if(count == 100)
			{
				cout<<"第"<<index+1<<"組player加入:"<<endl;
			}
			
			index++;
			maleVec.clear();
			femaleVec.clear();
		}
	}

private:
	vector<Male> maleVec;
	vector<Female> femaleVec;
	vector<Player> playerVec;
};

int main ()
{
	CMatch match;
	match.beginMatch();

	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
請按任意鍵繼續. . .



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章