【算法筆記】穩定婚姻匹配問題-GS算法


什么是穩定(婚姻)匹配問題

這里是百度百科。有N男N女,均為異性戀,每個人都對異性有好感度排序。如何將他們兩兩配對,才能盡可能使結果令每個人都滿意。

當然也有N男M女、多對一的情況,這里先不討論(網上有些大牛寫了論文)。

 

處理方案

被廣泛認可的算法是由美國數學家 David Gale 和 Lloyd Shapley 於1962年發明的 Gale-Shapley算法,簡稱GS算法。GS算法的思路如下:

先給N男N女從0~N-1分別編號,然后要求每個人寫出他們對異性的好感度排序。為了方便,這里N取4.比如0號男最喜歡3號女,其次是0號女,再次是1號女,最后是2號女,則0號男給出的排序為3 0 1 2.

下圖中展示了好感排序情況(隨機給出):

GS_data

第一輪,先讓每個男性向他們最喜歡的女性表白(也可以女性表白男性,同理)。例如0號男會先向3號女表白。如果一個女性同時收到了兩個表白,她會選擇接受自己最喜歡的那個男性。如3號女同時收到0號和2號的表白,接受0號。
第一次匹配結束后的情況:
0號男-3號女    1號男-0號女    3號男-1號女

第二輪,由於第一輪時只有2號男落單(慘),這次2號男選擇向自己第二喜歡的1號女表白。1號女接到表白后,會比較現任對象(3號男)和2號男,發現自己更喜歡2號男,於是與3號男分手,投入2號男的懷抱。
第二次匹配結束后的情況:
0號男-3號女    1號男-0號女    2號男-1號女

第三輪,3號男向自己第二喜歡的0號女表白,0號女比較現任配偶(1號男)和3號男,覺得自己還是更喜歡現任配偶,3號男被殘忍拒絕。這次匹配關系沒有發生變化。

第四輪,3號男向自己第三喜歡的2號女表白。2號女還沒有收到過表白,直接接受。
第四次匹配結束后的情況:
0號男-3號女    1號男-0號女    2號男-1號女    3號男-2號女

此時每個人都找到了配偶,匹配結束。

簡單總結一下,每一輪開始時:
①沒有配偶的男性選擇自己好感度最高而且沒表白過的女性表白。
②接到表白的女性比較現任配偶和新追求者的好感度,選擇與好感度更高的男性重新匹配。

 

GS算法的局限性

從算法過程容易看出,按照“男性表白女性”的策略對女性更有利,因為女性的配偶質量會不斷提升,而男性的配偶質量會不斷變差。相反則對男性有利。不同的表白策略得出的匹配結果很可能是不同的。

GS算法能否保證每個人都有對象

假設有一個男性A落單,由於男女人數相等,則必定還有一個女性B落單。
根據算法,B是被動接受表白,只要收到過一次表白,B就不可能落單。
而如果A沒有配偶,他會一直表白下去,將N個女性全部表白一遍。這個過程中B一定會收到表白,兩人匹配。

上述內容同時可以證明,該算法會在有限次運算后結束(運算次數小於n*n)。

GS算法的結果是否穩定

“穩定”是指:算法結束后,如果再進行一輪表白,一定不會出現男女雙方的選擇都更優的情況。
這一點容易證明。根據算法局限性,再進行表白,男性對新配偶的好感度只會下降。

假設男性A與女性B本應匹配(也就是說現在兩個人分別有自己的配偶,但是從好感度角度來說,他們都更希望彼此形成新的匹配),可以分兩種情況討論:
1.男性A曾對女性B表白,但此時兩人沒有匹配,說明女性B后來遇到了好感度更高的男性,假設不成立。
2.男性A不曾對女性B表白,說明男性A的配偶好感度排在女性B前面,假設不成立。

 

代碼實現

 1     #include<cstdio>
 2     #include<algorithm>
 3     #include<cmath>
 4     #include<iostream>
 5     #include<cstring>
 6     #include<string>
 7     using namespace std;
 8     const int MAXN = 0 + 5;
 9     int Num,nowMatch;
10     int Match_A[MAXN], Match_B[MAXN], Preference_A[MAXN][MAXN], Preference_B[MAXN][MAXN], Now[MAXN];
11     //Match數組記錄匹配情況,Preference[i][1..n]記錄好感排序
12     inline void init()
13     {//讀入、預處理
14       scanf("%d", &Num);
15       for (int i = 0; i < Num; ++i)
16         for (int j = 0; j < Num; ++j)
17           scanf("%d", &Preference_A[i][j]);
18       for (int i = 0; i < Num; ++i)
19         for (int j = 0; j < Num; ++j)
20           scanf("%d", &Preference_B[i][j]);
21       for (int i = 0; i < Num; ++i)
22         Match_A[i] = -1, Match_B[i] = -1;
23     }
24     bool Compare(int a, int b, int Obj)
25     {//比較追求當前的B[i]的兩個人在B[i]處的好感排序
26       int index_a = -1, index_b = -1;
27       for (int i = 0; i < Num; ++i)
28       {
29         if (Preference_B[Obj][i] == a)
30           index_a = i;
31         else if (Preference_B[Obj][i] == b)
32           index_b = i;
33       }
34       if (index_a < index_b) return true;
35       return false;
36     }
37     bool AllMatch()
38     {//判斷是否完成匹配
39       int count = 0;
40       for (int i = 0; i < Num; ++i)
41         if (Match_A[i] != -1)
42           count++;
43       if (count < Num) return false;
44       return true;
45     }
46     void Gale_Shapley()
47     {
48       while (! AllMatch())
49       {//算法會在所有人完成匹配后終止
50         for (int i = 0; i < Num; i ++)
51         {
52           if (Match_A[i] != -1) continue;
53           nowMatch = Match_B[Preference_A[i][Now[i]]];
54           //nowMatch是A[i]想要表白的B[i]目前的對象,沒有則為-1
55           if (nowMatch == -1 || Compare(i, nowMatch, Preference_A[i][Now[i]]))
56           {//如果B[i]沒有對象,或者B[i]對A[i]更有好感,則A[i]和B[i]匹配
57             Match_A[i] = Preference_A[i][Now[i]];
58             Match_A[nowMatch] = -1;
59             Match_B[Preference_A[i][Now[i]]] = i;
60           }
61           Now[i] ++;
62         }
63       }
64     }
65     inline void Output()
66     {
67       for (int i = 0; i < Num; ++i)
68       {
69         printf("A-%d is matched to B-%d\n", i, Match_A[i]);
70       }
71     }
72     int main()
73     {
74       init();
75       Gale_Shapley();
76       Output();
77       return 0;
78     }
GS code

 

測試一下最初給的那組數據

example

 

應用

雖然算法解決的問題是“穩定婚姻匹配”,但是真的按照這個算法來選對象豈不太簡單粗暴了…不過這好歹還是對象包分配
GS算法可以用於解決工作崗位的分配問題,例如某公司有n個崗位,m(m>=n)人競爭,可以根據公司和應聘者對彼此的好感度排序,利用算法算出最合適的人選。

 

漫談

如果把上文中的人視為點,好感關系視為線,就構成了一個二分圖匹配問題。問題就可以轉化為:根據已有的好感度排序,如何連線才能使得左右兩側的點一一相連,且連線結果盡量令人滿意。

匹配成功后的結果如圖所示,是一個一一映射:

如果把這個問題削弱一下,條件可以改為:每個人都對M(M<=N)名異性有好感,這種好感不分大小。如何使盡量多對互有好感的人相匹配。這個問題稱作二分圖最大匹配問題,可以用匈牙利算法求解。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM