问提描述:
有n个男孩m1,m2,…,mn 与n 个女孩w1,w2,wn。每一个男孩mi 都依照喜爱这n个女孩的程度列成一张表,最喜欢的女孩排在第1 位,最不喜爱的女孩排在第n 位;同样地,每一个女孩wi 也依照她喜爱n 个男孩的程度列成一张表。请写一个程序,把每一个男孩与女孩的喜爱表格读入,并且把男孩与女孩一一配对,使得:如果mp 与wq 是一对的话,那么,第一:对mp 的喜爱表格中排在wq 之前的女孩而言,她的伴侣在她的表格中一定排在mp 之前;第二:对wq 的喜爱表格中排在mp 之前的男孩而言,他的伴侣在他的表格中一定排在wq 之前。这就是稳定伴侣(Stable Marriage)问题。
解决这个问题的主要思想是男孩要不断向女孩表白,女孩决定接受哪个男孩。
第一轮,所有没有对象的男孩各自向自己心目中最喜欢的女孩表白,当男孩表白完之后女孩开始选择男孩,第一轮所有女孩都还没有对象,所以女孩所要做的事就是在所有向自己表白的男孩中选择自己最喜欢的做自己的伴侣就行了,但是这个伴侣只是暂时的。女孩选择完伴侣,第一轮结束,可能有两种情况:
所有男孩都有了对象,说明第一次就正好配对成功,结束程序。每个男孩最喜欢的女孩也最喜欢这个男孩。这简直是太完美了,不过这种情况出现的概率极小。
第二种就是有的男孩被拒绝了,有的女孩还没有被表白。这时候就要继续第一轮的过程:所有还没有对象的男孩在所有还没有拒绝他的女孩中选择最喜欢的一位向她表白;男孩表白完,所有女孩无论有没有对象,都要在所有向他表白的男孩中选择最喜欢的一个做自己的伴侣,如果女孩有伴侣,那么他就要放弃当前的伴侣,这样的话之前有对象的男孩可能又会变成单身。如此循环,只要还有男孩没有对象,就继续该过程,直到所有男孩都有对象了,就说明配对成功了,此时的组合即是最稳定组合,也就是说,即便女孩找到一个比自己当前伴侣更好的男孩,女孩在男孩心中却不如自己当前的伴侣,这样劈腿就不能成功了,也就是组合是稳定的。
java代码如下
package stabalpartner;
/**
* Created by yeqf on 5/25/15.
*/
public class StablePartner {
public static void main(String[] args) {
Boy[] boys = new Boy[5];
boys[0] = new Boy(0, 1, 2, 4, 3);
boys[1] = new Boy(4, 1, 3, 2, 0);
boys[2] = new Boy(2, 4, 0, 1, 3);
boys[3] = new Boy(2, 3, 1, 0, 4);
boys[4] = new Boy(3, 4, 0, 1, 2);
Girl[] girls = new Girl[5];
girls[0] = new Girl(1, 4, 3, 0, 2);
girls[1] = new Girl(2, 1, 3, 0, 4);
girls[2] = new Girl(0, 1, 3, 2, 4);
girls[3] = new Girl(3, 0, 1, 4, 2);
girls[4] = new Girl(4, 2, 1, 3, 0);
boolean flag = true;
while (flag) {
for (int i = 0; i < 5; i++) {
Boy boy = boys[i];
if (!boy.hasPart()) { //如果男孩没有伴侣
for (int j = 0; j < 5; j++) {
int girlId = boy.getGirlFromOrd(j).getId(); //得到该男孩心中排名为j的女孩的id
if (!boy.getGirlFromOrd(j).getIsRefused()) { //如果这个女孩没有拒绝过男孩
girls[girlId].getBoyFromId(i).setIsAspired(true); //男孩向女孩表白
break;
}
}
}
}
for (int i = 0; i < 5; i++) {
Girl girl = girls[i];
for (int j = 0; j < 5; j++) {
if (girl.getBoyFromOrd(j).getAspired()) { //如果该男孩向女孩表过白
//拒绝排名在该男孩后面的所有向该女孩表白的男孩
for (int k = j + 1; k < 5; k++) {
if (girl.getBoyFromOrd(k).getAspired()) {
int boyId = girl.getBoyFromOrd(k).getId();
boys[boyId].getGirlFromId(i).setIsRefused(true);
//如果男孩是该女孩的当前伴侣,则放弃该男孩,并把该男孩设置为单身
if (girl.getPartner() == boyId) {
boys[boyId].setPartner(-1);
}
}
}
girl.setPartner(girl.getBoyFromOrd(j).getId()); //女孩接受所有表白者中排名最高的男孩
boys[girl.getBoyFromOrd(j).getId()].setPartner(i); //并把男孩的伴侣设置为该女孩
break;
}
}
}
if (boys[0].hasPart() && boys[1].hasPart() && boys[2].hasPart() && boys[3].hasPart() && boys[4].hasPart()) {
flag = false;
}
}
for (int i = 0; i < 5; i++) {
System.out.println("boy " + i + " de partner is "
+ "girl " + boys[i].getPartner());
}
}
private static class Boy {
private GirlList[] girlLists = new GirlList[5];
private int partner = -1;
private class GirlList {
private boolean isRefused = false;
private int id;
public GirlList(int id) {
this.id = id;
}
public void setIsRefused(boolean flag) {
isRefused = flag;
}
public boolean getIsRefused() {
return isRefused;
}
public int getId() {
return id;
}
}
public Boy(int a, int b, int c, int d, int e) {
girlLists[0] = new GirlList(a);
girlLists[1] = new GirlList(b);
girlLists[2] = new GirlList(c);
girlLists[3] = new GirlList(d);
girlLists[4] = new GirlList(e);
}
public int getPartner() {
return partner;
}
public void setPartner(int partner) {
this.partner = partner;
}
public boolean hasPart() {
if (partner == -1) {
return false;
}
return true;
}
public GirlList getGirlFromOrd(int order) {
return girlLists[order];
}
public GirlList getGirlFromId(int id) {
int ord = 0;
while (girlLists[ord].getId() != id) {
ord++;
}
return girlLists[ord];
}
}
private static class Girl {
private BoyList[] boyLists = new BoyList[5];
private int partner = -1;
private class BoyList {
private boolean isAspired = false;
private int id;
public BoyList(int id) {
this.id = id;
}
public void setIsAspired(boolean flag) {
this.isAspired = flag;
}
public boolean getAspired() {
return isAspired;
}
public int getId() {
return id;
}
}
public Girl(int a, int b, int c, int d, int e) {
boyLists[0] = new BoyList(a);
boyLists[1] = new BoyList(b);
boyLists[2] = new BoyList(c);
boyLists[3] = new BoyList(d);
boyLists[4] = new BoyList(e);
}
public int getPartner() {
return partner;
}
public void setPartner(int partner) {
this.partner = partner;
}
public boolean hasPart() {
if (partner == -1) {
return false;
}
return true;
}
public BoyList getBoyFromOrd(int ord) {
return boyLists[ord];
}
public BoyList getBoyFromId(int id) {
int ord = 0;
while (boyLists[ord].getId() != id) {
ord++;
}
return boyLists[ord];
}
}
}