我想编写一个程序,将 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之后那个男人的第一顺位。
感谢您的帮助。
答案 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;
}
}