前言:
前不久被要求写一个关于稳定婚配问题的算法,稳定婚配是一个很经典的问题,这里我就不多去描述他了,你在网上能找到一堆。解决稳定婚配问题的一个著名算法是G-S算法,也叫延迟认可算法,具体不再描述。此算法只能的到一个单边最优的解,不久前在一本书上看见过求稳定匹配的所有可能的解的算法(穷举法)。这几天由于 新型肺炎 导致特别闲(希望肺炎快点结束),于是打算写一下。
具体方法(C++实现):
1.算法思想:
首先找到一个完美匹配,然后在判断此完美匹配中是否有不稳定因素,如果有,则抛弃这个完美匹配(即这个完美匹配不是稳定匹配),如果没有不稳定因素,则输出此完美匹配(这个完美匹配就是稳定匹配),然后继续找到下一个完美匹配,判断…
2.具体代码:
①. 首先定义一个数据结构用来存放每个人的信息:
typedef struct tagPartner
{
string name; //名字
int next = 0; //下一个匹配对象
int current = -1; //当前配对,-1表示还没有配对
int pCount = UNIT_COUNT; //好感列表中个数
int* perfect = new int[UNIT_COUNT]; //好感列表
}PARTNER;
②. 找到完美匹配,并判断是否稳定(主要算法)
//主要算法部分
void SearchStableMatch(int index, PARTNER *boys, PARTNER *girls)
{
//如果index==UNIT_COUNT,表明一组完美匹配成功,判断其是否稳定
if (index == UNIT_COUNT)
{
if (IsStableMatch(boys, girls))//判断是否为稳定匹配
{
PrintResult(boys, girls, UNIT_COUNT);//打印
}
return;
}
//为编号为index的boy匹配对象,即找完美匹配
for (int i = 0; i < boys[index].pCount; i++)
{
int gid = boys[index].perfect[i];//boy匹配的girl编号
if (!IsPartnerAssigned(&girls[gid]) && IsFavoritePartner(&girls[gid], index))//如果女孩gid没有对象,且index男士在她喜欢的列表中
{
boys[index].current = gid;//将index男士和gid女士匹配为一组
girls[gid].current = index;
SearchStableMatch(index + 1, boys, girls);//给下一个男士匹配对象
//下面两个语句即递归调用结束,即一个完美匹配成功后执行的语句
//回归到全部单身的状态
boys[index].current = -1;
girls[gid].current = -1;
}
}
}
③.判断完美匹配是否稳定
//判断匹配是否稳定
bool IsStableMatch(PARTNER *boys, PARTNER *girls)
{
for (int i = 0; i < UNIT_COUNT; i++)
{
//找到男孩当前配对对象在自己的偏好列表中的位置
int gpos = GetPerfectPosition(&boys[i], boys[i].current);
//在position位置之前的配对对象,男孩喜欢她们胜过current
for (int k = 0; k < gpos; k++)
{
int gid = boys[i].perfect[k];
//找到男孩在这个女孩的好感表中的位置
int bpos = GetPerfectPosition(&girls[gid], i);
//找到女孩的当前配对对象在这个女孩的好感表中的位置
int cpos = GetPerfectPosition(&girls[gid], girls[gid].current);
if (bpos < cpos)
{
//女孩也是喜欢这个男孩胜过喜欢自己当前的配对对象,这是不稳定因素
return false;
}
}
}
return true;
}
④. 其他辅助函数
//获得编号为id的人在 partner好感列表中的位置
int GetPerfectPosition(PARTNER *partner, int id)
{
for (int i = 0; i < partner->pCount; i++)
{
if (partner->perfect[i] == id)
{
return i;
}
}//返回一个非常大的值,意味着根本配不上对
return 9999999;
}
void PrintResult(PARTNER *boys, PARTNER *girls, int count)
{
for (int i = 0; i < count; i++)
{
out << boys[i].name << "<---> " << girls[boys[i].current].name << endl;
}
out << "=====&