Gale-Shapley算法

时间:2019-10-01 08:21:11

标签: java algorithm

我想编写一个程序,将 n 位男性[0,1,2,...,n-1]与 n 位女性[0,1, 2,...,n-1]根据他们的喜好。这些偏好用 n x n 矩阵表示,一个代表男性,一个代表女性。

            [ 0 2 1 ]
  E.g. men: [ 1 0 2 ]. The rows represent each man from 0 to 2, and per row we see a man's 'top 3'.
            [ 1 2 0 ]
  In this example: man 0 prefers woman 0 over woman 2; woman 1 is both man1's and man2's most prefered partner.

现在,我要确保匹配尽可能地理想。这可以通过使用Gale-Shapley算法来完成。

我有两个问题:

  • 假设m0和m1都以w0为首选。然后,我们必须查看w0的首选项:假设m0排名较高,那么(m0,w0)是(临时)匹配项。接下来我该怎么办?我首先将m2与他的第一顺位匹配吗?或者-由于m1仍然免费-我是否将m1与他的第二顺位匹配?

  • 我已经实现了如下算法:

基本上,输入包括男性和女性的偏好矩阵。结果应为res = [2,0,1]之类的数组,这意味着男人2与女人0匹配,m0与w1匹配,而m1与w2匹配。

    public int[] match(int[][] men, int[][] women) {

    int n = men.length;
    boolean[] menFree = new boolean[n];
    Arrays.fill(menFree, true);
    int[] res = new int[n];
    Arrays.fill(res, -1);
    int free = n;
    int m = 0;
    while (free > 0 && m<n) { 
        for (int i = 0; i < n; i++) {
            if(menFree[i]){
                int w = men[i][m];
                if(res[w]==-1){
                    res[w]=i;
                    menFree[i]=false;
                    free--;
                } else {
                    int c = res[w];
                    int colI = 0;
                    int colC = 0;
                    for(int j=0;j<n;j++){ 
                        if(women[w][j]==i){
                            colI = j;
                        } else if(women[w][j]==c){
                            colC = j;
                        }
                    }
                    if(colI<colC){
                        res[w]=i;
                        menFree[c]=true;
                        menFree[i]=false;
                    } else {
                        //do nothing or change column here, depending on answer to my first question.
                    }
                }
            }
        }
        m++; 
    }
    return res;
    }

如您所见,当一个男人(= M)的竞争对手的位置高于M自己的位置时,我不确定该如何处理else-part。另外,如果事实证明我当时应该寻找M的第二选择,我该怎么做?仍然有可能我必须回到M之后那个男人的第一顺位。

感谢您的帮助。

1 个答案:

答案 0 :(得分:2)

我读了wiki。而且我实现了自己。我想我理解了,但是我的程序并不漂亮。只是为了交流。

package algorithm;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class GaleShapley {

    public static void main(String[] args) {
        int[][] men = {{1, 2, 0}, {0, 1, 2}, {2, 1, 0}};
        int[][] women = {{1, 2, 0}, {0, 1, 2}, {2, 1, 0}};
        int[] res = match(men, women);
        for (int i : res)
            System.out.println(i);
    }

    static int[] match(int[][] men, int[][] women) {
        Map<Integer, Integer> temp = new HashMap<>();
        int size = men.length;
        boolean[] menFree = new boolean[size];
        boolean[] womenFree = new boolean[size];
        Arrays.fill(menFree, true);
        Arrays.fill(womenFree, true);
        ArrayList<Integer> stillFree = new ArrayList<>();

        while (stillFree.size() + temp.size() < size) {
            for (int i = 0, j = 0; i < size; i++, j = 0) {
                if (menFree[i]) {
                    for (; j < size; j++) {
                        //if the woman is free,make them a pair
                        if (womenFree[men[i][j]]) {
                            // make woman and man i pair, the woman's index is men[i][j]
                            temp.put(men[i][j], i);
                            menFree[i] = false;
                            womenFree[men[i][j]] = false;
                            break;
                        } else {
                            // the woman is not free,check her pair is whether stable
                            int pairMan = temp.get(men[i][j]);
                            boolean stable = checkStable(pairMan, i, men[i][j], women);
                            // not stable break them and make new pair
                            if (!stable) {
                                temp.put(men[i][j], i);
                                menFree[i] = false;
                                menFree[pairMan] = true;
                                break;
                            }
                        }
                    }
                    // if man i is still free , it means that he can't find a woman
                    if (menFree[i])
                        stillFree.add(i);
                }
            }
        }
        int[] stablePair = new int[2 * temp.size()];
        int i = 0;
        for (Map.Entry<Integer, Integer> entry : temp.entrySet()) {
            stablePair[i] = entry.getValue();
            i++;
            stablePair[i] = entry.getKey();
            i++;
        }
        return stablePair;
    }

    static boolean checkStable(int pairMan, int currentMan, int woman, int[][] women) {
        // index of pairMan and currentMan
        int p = 0, c = 0;
        for (int i = 0; i < women.length; i++) {
            if (women[woman][i] == pairMan)
                p = i;
            else if (women[woman][i] == currentMan)
                c = i;
        }
        // p<c : the woman love p more than c, they are stable
        return p < c;
    }
}