婚姻匹配算法

/*Copyright (c)2018, 东北大学软件学院学生          
* All rightsreserved          
* 文件名称:a.cpp          
* 作   者:孔云         
*问题描述:参考注释*/
#include <iostream>
#include <cstdlib>
using namespace std;
bool finish_or_not(int, int *);
bool current_male_is_better(int num, int *male_rank_in_female, int current, int chasing);
int main(){
   int num = 5;
   int female_rank_in_male[5][5] = { { 2, 1, 4, 5, 3 }, { 4, 2, 1, 3, 5 }, { 2, 5, 3, 4, 1 }, { 1, 4, 3, 2, 5 }, { 2, 4, 1, 5, 3 } };
   int male_rank_in_female[5][5] = { { 5, 1, 2, 4, 3 }, { 3, 2, 4, 1, 5 }, { 2, 3, 4, 5, 1 }, { 1, 5, 4, 3, 2 }, { 4, 2, 5, 3, 1 } };

   for (int i = 0; i < num; i++){
       cout << "男生 " << i << " 心目中妹子的排行:";
       for (int j = 0; j < num; j++){
           cout << female_rank_in_male[i][j] << " ";
       }
       cout << endl;
   }
   cout << endl;
   for (int i = 0; i < num; i++){
       cout << "女生 " << i << " 心目中男生的排行:";
       for (int j = 0; j < num; j++){
           cout << male_rank_in_female[i][j] << " ";
       }
       cout << endl;
   }

   //男生和妹子正在约会的对象
   int *date_of_male = new int[num];
   int *date_of_female = new int[num];
   for (int i = 0; i < num; i++){
       date_of_male[i] = 0;
       date_of_female[i] = 0;
   }

   //男生追求过的妹子的数量
   int *num_of_chased_female = new int[num];
   for (int i = 0; i < num; i++){
       num_of_chased_female[i] = 0;
   }

   do{//如果有男生没有对象
       for (int i = 0; i < num; i++){//按序号遍历所有男生
           cout << endl << "正在查看男生 " << i + 1 << " 有没有对象..." << endl;
           if (date_of_male[i] == 0){//如果某男生没有对象
               cout << "男生 " << i + 1 << " 没有对象!" << endl;
               //该男生准备追的妹子(该男生优先表中还没追求过的排名最高的妹子)
               int female_to_chase = female_rank_in_male[i][num_of_chased_female[i]];
               //该男生准备追的妹子的现任
               int date_of_female_to_chase = date_of_female[female_to_chase - 1];
               cout << "男生 " << i + 1 << " 准备追妹子 " << female_to_chase;
               if (date_of_female_to_chase != 0){
                   cout << ",妹子现任是 " << date_of_female_to_chase << endl;
               }
               else{
                   cout << ",妹子目前是单身的呢~" << endl;
               }

               if (date_of_female_to_chase == 0){//如果该男生准备追的妹子没有现任
                   date_of_male[i] = female_to_chase;//该男生的对象变成准备追的妹子
                   date_of_female[female_to_chase - 1] = i + 1;//男生准备追的妹子的对象变成该男生
                   cout << "这样子的话,男生 " << i + 1 << " 和妹子 " << female_to_chase << " 在一起了!" << endl;
               }
               else if (current_male_is_better(num, male_rank_in_female[female_to_chase - 1], date_of_female_to_chase, i + 1)){
                   //如果该男生准备追的妹子的现任在妹子心目中比该男生更好,则什么也不做
                   cout << "所以!男生 " << i + 1 << " 被妹子 " << female_to_chase << " 拒绝了!" << endl;
               }
               else{//如果该男生比该男生准备追的妹子的现任在妹子心目中更好
                   date_of_male[date_of_female_to_chase - 1] = 0;//该男生准备追的妹子的现任回到单身状态
                   date_of_male[i] = female_to_chase;//该男生的对象变成准备追的妹子
                   date_of_female[female_to_chase - 1] = i + 1;//该男生准备追的妹子的对象变成该男生
                   cout << "所以!男生 " << i + 1 << " 和妹子 " << female_to_chase << " 在一起了!" << endl;
                   cout<< "与此同时,不幸的是,男生 " << date_of_female_to_chase << " 变成单身狗了QAQ" << endl;
               }

               num_of_chased_female[i]++;//该男生追过的妹子数量加1
           }
           else{
               cout << "男生已经跟妹子 " << date_of_male[i] << " 在一起了呢~~下一个吧~~~" << endl;
           }
       }
   } while (finish_or_not(num, date_of_male) == false);

   //最后的输出
   cout << endl << "┌───故事的结局───┐"<<endl;
   cout << "│                      │" << endl;
   for (int i = 0; i < num; i++){
       cout << "│     男生" << i + 1 << " - "<< "女生" << date_of_male[i] <<"    │"<< endl;;
   }

   cout << "│                      │" << endl;
   cout << "└───────────┘" << endl << endl;
   delete[] date_of_male;
   delete[] date_of_female;
   delete[] num_of_chased_female;
   system("pause");
   return 0;
}

bool finish_or_not(int num, int *date_of_male){

   for (int i = 0; i < num; i++){
       if (date_of_male[i] == 0){
           cout << "还有单身狗......再来~" << endl;
           return false;
       }
   }
   cout << endl << "已全部脱离单身狗行列!!!" << endl;
   return true;
}

//比较某妹子现在的对象和追求者哪个在她心目中排行更高
//注意数组参数是一维(一位妹子的优先表而不是所有妹子的优先表)
bool current_male_is_better(int num, int *male_rank_in_female, int current, int chasing){
   int rank_of_current, rank_of_chasing;
   for (int i = 0; i < num; i++){
       if (male_rank_in_female[i] == current){
           rank_of_current = i;
       }
       if (male_rank_in_female[i] == chasing){
           rank_of_chasing = i;
       }
   }
   cout << "在妹子心目中现任排名是 " << rank_of_current << " ,而追求者排名则是 " << rank_of_chasing << endl;
   if (rank_of_current < rank_of_chasing)
       return true;
   else
       return false;
}

运行结果:


注:

在组合数学,稳定婚姻问题指:
有n男n女,每人都按他对(异性)对象的喜好程度按1至n排列。安排男女结婚,使得下列情形为真:
     1. 在n男n女中的任意两对夫妇(M, W)和(m, w),都不存在
     2. M男对w女喜好度大于现任妻子W女,并且w女对M男喜好度也大于现任丈夫m男
的情形发生,此种情形称为不稳定。

Gale-Shapley 算法

        1962年,美国数学家 David Gale 和 Lloyd Shapley 发明了一种寻找稳定婚姻的策略。不管男女各有多少人,也不管他们的偏好如何,应用这种策略后总能得到一个稳定的搭配。换句话说,他们证明了稳定的婚姻搭配 总是存在的。有趣的是,这种策略反映了现实生活中的很多真实情况。

        在这种策略中,男孩儿将一轮一轮地去追求他中意的女子,女子可以选择接受或者拒绝他的追求者。第一轮,每个男孩儿都选择自己名单上排在首位的女 孩儿,并向她表白。此时,一个女孩儿可能面对的情况有三种:没有人跟她表白,只有一个人跟她表白,有不止一个人跟她表白。在第一种情况下,这个女孩儿什么 都不用做,只需要继续等待;在第二种情况下,接受那个人的表白,答应暂时和他做情侣;在第三种情况下,从所有追求者中选择自己最中意的那一位,答应和他暂 时做情侣,并拒绝所有其他追求者。

        第一轮结束后,有些男孩儿已经有女朋友了,有些男孩儿仍然是单身。在第二轮追女行动中,每个单身男孩儿都从所有还没拒绝过他的女孩儿中选出自己 最中意的那一个,并向她表白,不管她现在是否是单身。和第一轮一样,女孩儿们需要从表白者中选择最中意的一位,拒绝其他追求者。注意,如果这个女孩儿已经 有男朋友了,当她遇到了更好的追求者时,她必须拒绝掉现在的男友,投向新的追求者的怀抱。这样,一些单身男孩儿将会得到女友,那些已经有了女友的人也可能 重新变成光棍。在以后的每一轮中,单身男孩儿继续追求列表中的下一个女孩儿,女孩儿则从包括现男友在内的所有追求者中选择最好的一个,并对其他人说不。这 样一轮一轮地进行下去,直到某个时候所有人都不再单身,下一轮将不会有任何新的表白发生,整个过程自动结束。此时的婚姻搭配就一定是稳定的了。

猜你喜欢

转载自blog.csdn.net/u012369559/article/details/79753089