zoukankan      html  css  js  c++  java
  • 数字化婚姻配对尝试问题(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 ");
    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 ");
    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 ");
    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:-
    --------------------- 

  • 相关阅读:
    延迟任务
    xxl-job 执行器调度
    Linux查看日志定位问题
    docker 远程连接
    sqlserver的备份和恢复 命令非计划任务
    创建带包含列的索引 sqlserver
    exec sp_executesql (sqlsugar使用中的坑)的坑。执行sql非常慢
    vue elementui的表单设计器
    将docker容器的配置导出为docker-compose.yml
    异步通信,rpc通信的笔记
  • 原文地址:https://www.cnblogs.com/ly570/p/11060564.html
Copyright © 2011-2022 走看看