稳定婚配问题的所有可能解

前言:
前不久被要求写一个关于稳定婚配问题的算法,稳定婚配是一个很经典的问题,这里我就不多去描述他了,你在网上能找到一堆。解决稳定婚配问题的一个著名算法是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 << "=====&
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值