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存储在男士编号对应下标中,这样在用男士编号查询时,可以不用遍历数组而可以直接读出相应优先级进行比较。
类似的问题还有船舶停靠问题,船和港口之间类比于男士和女士。对船来说,先安排的港口有更高的优先级;对港口来说,后到的船有更高的优先级。