G-S稳定匹配算法详解

G-S稳定匹配算法详解

GS算法是解决稳定匹配问题(stable matching)的一个优秀的算法。

下面以男女配对的例子来介绍稳定匹配问题并阐述GS算法的具体步骤。

GS算法,全称Gale-Shapley算法。


一、问题描述及假设

  • 有n个单身男性集合M = {m1, m2, …, mn}和n个单身女性集合W = {w1, w2, …, wn}

  • 假设每个男性对不同女性的喜好程度都不同,单身女性亦如是。

  • 男性mi(1 <= i <= n)有一张属于自己的对n个女性的排序表,mi把他最爱慕的女性放在第一位,第二爱慕的女性放在第二位,以此类推,排名越靠前女性表示mi越爱慕的该女性。同样地,女性wi(1 <= i <= n)也有一张属于自己的对n个男性的排序表,排名越靠前的男性越受该女性的喜爱。

  • 每个人最终都要有伴侣


二、伪代码

image-20200302163507613

引自《算法设计》(Jon Kleinberg ,Eva Tardos 著 ,张立昂,屈婉玲 译)


三、具体代码

C++实现

#include<iostream>
using namespace std;

// describe where there is a woman is single in a man[a]'s list or not
// if have single woman return 1,else return 0
bool mans_date(int a, bool**b, int number) {
	for (int i = 0; i < number; i++)
		if (b[a][i] == 0)
			return 1;
	return 0;
}

// if all the mans have the lovers return 0,else 1
bool have_man(bool*mans_state, int number, int &index) {
	for (int i = 0; i < number; i++)
		if (mans_state[i] == 0)
		{
			index = i;
			return 1;
		}
	return 0;
}

// G-S algorithm
// number----the mans and women number
// man ------mans'priority matrix
// women ----women's priority matrix
int* gs(int number, int **man, int **women)
{
	//mans and women state describe they are single or not 
	bool *mans_state = new bool[number];
	bool *women_state = new bool[number];

	// describe a lovers 
	int *woman_man_pair = new int[number];

	// mans_women describe a man and a women where had date or not
	bool **mans_women;
	mans_women = new bool*[number];
	for (int i = 0; i < number; i++)
		mans_women[i] = new bool[number];
	
	//initialize
	for (int i = 0; i < number; i++)
	{
		mans_state[i] = 0;
		women_state[i] = 0;
	}
	for (int i = 0; i < number; i++)
		for (int j = 0; j < number; j++)
			mans_women[i][j] = 0;
    
	//use inverse to reduce complexity
	int **inverse;
	inverse = new int*[number];
	for (int i = 0; i < number; i++)
		inverse[i] = new int[number];
	for (int i = 0; i < number; i++)
		for (int j = 0; j < number; j++)
			inverse[i][women[i][j]] = j;

	int index = 0;
	while (have_man(mans_state, number, index) && mans_date(index, mans_women, number))
	{

		int tmp_man = index;
		int tmp_woman;
		//select the women tmp_man like most and this woman is single
		for (int i = 0; i < number; i++)
			if (mans_women[tmp_man][man[tmp_man][i]] == 0)
			{
				tmp_woman = man[tmp_man][i];
				break;
			}

		if (women_state[tmp_woman] == 0)
		{
			// tmp_man and tmp_woman is not single
			women_state[tmp_woman] = 1;
			mans_state[tmp_man] = 1;

			//tmp_woman's lover is tmp_man
			woman_man_pair[tmp_woman]=tmp_man;
			//tmp_man and tmp_woman had a date
			mans_women[tmp_man][tmp_woman] = 1;
		}
		else {
			//m2-----tmp_woman's lover now
			int m2 = woman_man_pair[tmp_woman];
			//compair m2 with tmp_man,if tmp_man is more excellent ,tmp_woman will date with tmp_man and break up with m2
			if (inverse[tmp_woman][m2] > inverse[tmp_woman][tmp_man])
			{
				//tmp_woman's lover is tmp_man
				woman_man_pair[tmp_woman] = tmp_man;
				//m2 back to single
				mans_state[m2] = 0;
				//tmp_man is not single
				mans_state[tmp_man] = 1;
				//tmp_woman's lover is tmp_man
				mans_women[tmp_man][tmp_woman] = 1;
			}
			else {
				//tmp_man and tmp_woman had a date
				mans_women[tmp_man][tmp_woman] = 1;
			}
		}
	}
	//return the woman mans'like in man'order
	int *end_pair = new int[number];
	for (int i = 0; i < number; i++)
		end_pair[woman_man_pair[i]] = i;
	return end_pair;
}
int main() {
	
	int number, **mans, **women;

	cout << "input the number of man or woman:";
	cin >> number;

	mans = new int*[number];
	women = new int*[number];

	//initialize
	for (int i = 0; i < number; i++)
	{
		mans[i] = new int[number];
		women[i] = new int[number];
	}
	cout << "input mans' priority matrix" << endl;
	for (int i = 0; i < number; i++) {
		for (int j = 0; j < number; j++)
			cin >> mans[i][j];
	}
	cout << "input women's priority matrix" << endl;
	for (int i = 0; i < number; i++) {
		for (int j = 0; j < number; j++)
			cin >> women[i][j];
	}

	for (int i = 0; i < number; i++) {
		for (int j = 0; j < number; j++)
		{
			mans[i][j] -= 1;
			women[i][j] -= 1;
		}
	}

	cout << endl << endl;
	int*end_pair2 = new int[number];
	end_pair2 = gs(number, mans, women);
	for(int i=0;i<number;i++)
		cout <<end_pair2[i]+1<<"  ";
	return 0;
}

其中使用了反转的思想实现降低时间复杂度的需要


四、输入输出

输入:
在这里插入图片描述


输出:

3 1 2 5 4

经验证,是稳定匹配


五、总结

对于男性而言,G-S算法是最理想的,因为男性匹配到的都是最佳有效伴侣(best(m))

而对于女性来说匹配到的最差有效伴侣(worst(w))

虽然男性可能常常会被拒绝的一方,是但是只要不断尝试,最终得到的结果就是最美好的

这启示我们不管追寻爱情还是做其他事前,应该积极主动一点才会有最好的结局。

  • 7
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
ORB-SLAM是一种基于特征点的视觉SLAM算法,它使用ORB特征点来进行特征匹配。ORB特征点是一种既能够快速检测又能够准确描述图像特征的算法。ORB特征点的检测和描述分别使用了FAST角点检测算法和BRIEF描述子算法。ORB-SLAM使用了基于词袋模型的方法来进行特征匹配,具体来说,ORB-SLAM将所有的ORB特征点分成若干个不同的视觉词汇,然后使用BoW(Bag of Words)模型来描述每个图像。在ORB-SLAM中,特征匹配主要分为两个步骤:词袋匹配和光流法匹配。词袋匹配是通过计算两个图像的词袋向量之间的距离来进行的,而光流法匹配则是通过计算两个图像中的特征点在相邻帧之间的运动来进行的。 以下是一个ORB-SLAM特征匹配算法的示例代码: ```c++ // ORB特征点检测和描述 cv::Ptr<cv::ORB> orb = cv::ORB::create(); std::vector<cv::KeyPoint> keypoints1, keypoints2; cv::Mat descriptors1, descriptors2; orb->detectAndCompute(img1, cv::noArray(), keypoints1, descriptors1); orb->detectAndCompute(img2, cv::noArray(), keypoints2, descriptors2); // 词袋匹配 cv::Ptr<cv::DescriptorMatcher> matcher = cv::DescriptorMatcher::create("BruteForce-Hamming"); std::vector<cv::DMatch> matches; matcher->match(descriptors1, descriptors2, matches); // 光流法匹配 std::vector<cv::Point2f> points1, points2; for (auto match : matches) { points1.push_back(keypoints1[match.queryIdx].pt); points2.push_back(keypoints2[match.trainIdx].pt); } std::vector<uchar> status; std::vector<float> err; cv::calcOpticalFlowPyrLK(img1, img2, points1, points2, status, err); // 输出匹配结果 for (int i = 0; i < matches.size(); i++) { if (status[i]) { cv::DMatch match = matches[i]; cv::Point2f pt1 = keypoints1[match.queryIdx].pt; cv::Point2f pt2 = keypoints2[match.trainIdx].pt; std::cout << "Match " << i << ": (" << pt1.x << ", " << pt1.y << ") -> (" << pt2.x << ", " << pt2.y << ")" << std::endl; } } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Joshua_yi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值