Gale-Shapley稳定配对问题

  Gale-Shapley算法是这两个人提出来的一种稳定匹配问题。主要是当存在自由男时,进行以下操作:

①每一位自由男在所有尚未拒绝她的女士中选择一位被他排名最优先的女士;
②每一位女士将正在追求她的自由男与其当前男友进行比较,选择其中排名优先的男士作为其男友,即若自由男优于当前男友,则抛弃前男友;否则保留其男友,拒绝自由男。
③若某男士被其女友抛弃,重新变成自由男。
  其C++实现如下:(读取对应文件格式过于繁琐,导致数组初始化所需代码行数较多)
  1     #include <iostream>
  2     #include <fstream>
  3     #include <string>
  4     #include <cstdio>
  5     #include <cstdlib>
  6     #include <cstring>
  7 
  8     using namespace std;
  9 
 10     int get_digit(const string str)   //get digit from string
 11     {
 12         string substr;
 13         int first_pos,Girl_pos,last_pos,num,length;
 14         char cstring[10];
 15         Girl_pos = str.find('G');
 16         if(Girl_pos != string::npos)
 17         {
 18             last_pos = str.find(' ');
 19             length = last_pos - Girl_pos-1;
 20             substr = str.substr(Girl_pos+1,length);
 21             strcpy(cstring,substr.c_str());
 22             num = atoi(cstring);
 23         }
 24         first_pos = str.find('B');
 25         if(first_pos != string::npos)
 26         {
 27             last_pos = str.find(':');
 28             length = last_pos - first_pos-1;
 29             substr = str.substr(first_pos+1,length);
 30             strcpy(cstring,substr.c_str());
 31             num = atoi(cstring);
 32         }
 33         return num;
 34     }
 35 
 36     int main()
 37     {
 38         int num;
 39         int Man[205][205];
 40         int Woman[205][205];
 41         int manMatch[205];
 42         int womanMatch[205];
 43         string str,substr;
 44         ifstream mfile,wmfile;
 45         ofstream outfile;
 46         mfile.open("boys_rankings.txt",ifstream::in);
 47         wmfile.open("girls_rankings.txt",ifstream::in);
 48         //read information from boys_ranking
 49         if(!mfile){
 50             cout << "error"<<endl;
 51             exit(1);
 52         }
 53         while(mfile.peek() != EOF){
 54             getline(mfile,str,'\n');
 55             int i=0;
 56             int j=0;
 57             int temp,pri=0;
 58             for(string::iterator it=str.begin();it!=str.end();++it)
 59             {
 60                 if(*it != ' ')i++;
 61                 else{
 62                     substr = str.substr(j,i-j+1);
 63                     num = get_digit(substr);
 64                     if(j == 0)temp = num;
 65                     else {
 66                         Man[temp][pri] = num;
 67                         pri++;
 68                     }
 69                     j=++i;
 70                 }
 71             }
 72             substr = str.substr(j,i-j+1);
 73             substr.append(" ");
 74             num = get_digit(substr);
 75             Man[temp][pri] = num;
 76         }
 77        //read information from girls_ranking
 78         if(!wmfile){
 79             cout << "error"<<endl;
 80             exit(1);
 81         }
 82         while(wmfile.peek() != EOF){
 83             getline(wmfile,str,'\n');
 84             int i=0;
 85             int j=0;
 86             int temp,pri=0;
 87             for(string::iterator it=str.begin();it!=str.end();++it)
 88             {
 89                 if(*it != ' ')i++;
 90                 else{
 91                     substr = str.substr(j,i-j+1);
 92                     num = get_digit(substr);
 93                     if(j == 0)temp = num;
 94                     else {
 95                         Woman[temp][num] = pri;      //store the exchanged data with array number
 96                         pri++;                       //easier to judge girls' choice
 97                     }
 98                     j=++i;
 99                 }
100             }
101             substr = str.substr(j,i-j+1);
102             substr.append(" ");
103             num = get_digit(substr);
104             Woman[temp][num] = pri;
105         }
106         /*
107         for(int j=0;j<200;j++){
108         for(int i=0;i<200;i++)
109             cout << "Man 0 "<<i<<":"<<Woman[j][i]<<endl;
110         getchar();
111         }
112         */
113         memset(manMatch,0,sizeof(int)*205);
114         for(int i=0; i<205; i++)womanMatch[i]=200;
115         int i = 0;
116         int x,goon;
117         goon = -1;
118         while(i < 200)
119         {
120             int m = manMatch[i];  //the best match array number
121             int v = Man[i][m];    //id of the best girl
122             if(womanMatch[v] == 200){
123                 womanMatch[v] = i;
124                 i++;
125                 if(i <= goon)
126                     i = goon;
127             }
128             else {
129                 if(Woman[v][i] < Woman[v][womanMatch[v]]) //now the man is better
130                 {
131                     x = womanMatch[v];   //x is the rejected man's number
132                     womanMatch[v] = i;
133                     manMatch[x]++;
134                     if(goon <= i)
135                         goon = i+1;     //goon is the next to do with
136                     i = x;
137                 }
138                 else if(Woman[v][i] > Woman[v][womanMatch[v]])
139                 {
140                     manMatch[i]++;
141                 }
142             }
143         }
144         outfile.open("result.txt",ofstream::out);
145         for(int i=0; i<200;i++)
146             outfile <<"B "<<i<<"   ->   "<<"G "<<Man[i][manMatch[i]]<<endl;
147         return 0;
148     }

  其中,对于女士相应优先级的数组初始化时采用的是与男士不一样的初始化方法,可以将女士对男士的匹配从O(n)降至O(1),主要思想就是交换存储下标和男士编号,本来是下标对应优先级,即0下标存储的男士编号优先级最高;但此时反过来,将0存储在男士编号对应下标中,这样在用男士编号查询时,可以不用遍历数组而可以直接读出相应优先级进行比较。

  类似的问题还有船舶停靠问题,船和港口之间类比于男士和女士。对船来说,先安排的港口有更高的优先级;对港口来说,后到的船有更高的优先级。

posted @ 2014-10-21 15:02  Sprink  阅读(382)  评论(0编辑  收藏  举报