问题的描述
在这里就不赘述了,你能搜到这篇文章,那肯定知道只算法的背景是啥
解决思路
- 男生向还未拒绝其的女生中选出优先级最高的,并向其求婚
- 女生如果没有已经被优先级更高的男生求婚,则答应(女生以后可以反悔)。 如果反之,则拒绝
- 对此步骤进行loop,直到没有求婚发生
这篇文章,讲一个自己实现的GS算法的版本
看过一些博文,比如这篇文章 https://blog.csdn.net/lonfee88/article/details/6678190
文章使用的代码
上面那篇文章使用的代码是这样的,很清晰。
def find_stable_matching(man_preferences, woman_preferences):
"""
Gale-Shapely Algorithm
:param man_preferences:
:param woman_preferences:
:return:
"""
length = len(man_preferences)
is_man_free = [True] * length
is_woman_free = [True] * length
isManProposed = [[False for i in range(length)] for j in range(length)]
match = [(-1, -1)] * length
while True in is_man_free:
indexM = is_man_free.index(True)
if False in isManProposed[indexM]:
indexW = -1
for i in range(length):
w = man_preferences[indexM][i]
if isManProposed[indexM][w] is False:
indexW = w
break
isManProposed[indexM][indexW] = True
if is_woman_free[indexW] is True:
is_woman_free[indexW] = False
is_man_free[indexM] = False
match[indexM] = (indexM, indexW)
else:
indexM1 = -1
for j in range(length):
if match[j][1] == indexW:
indexM1 = j
break
if woman_preferences[indexW].index(indexM) < woman_preferences[indexW].index(indexM1):
is_man_free[indexM1] = True
is_man_free[indexM] = False
match[indexM] = (indexM, indexW)
print(match)
return match
这个算法没问题, 结果也是对的。 但是我认为有点拖沓, 还可以进行精简。
我们输入 这样两个二维矩阵
MP = [[1, 4, 3, 6, 2, 5, 8, 7, 9, 0],
[2, 1, 0, 3, 4, 8, 5, 9, 7, 6],
[4, 3, 8, 9, 0, 2, 1, 7, 6, 5],
[2, 7, 6, 1, 4, 3, 8, 0, 9, 5],
[5, 3, 8, 4, 2, 0, 7, 6, 1, 9],
[5, 0, 1, 7, 2, 8, 9, 4, 6, 3],
[6, 2, 9, 8, 0, 7, 5, 1, 4, 3],
[9, 7, 1, 8, 0, 2, 5, 6, 3, 4],
[8, 0, 5, 9, 6, 7, 1, 2, 4, 3],
[7, 9, 1, 6, 2, 0, 5, 8, 4, 3]]
WP = [[3, 5, 0, 6, 9, 4, 8, 7, 2, 1],
[0, 1, 3, 2, 7, 8, 5, 9, 4, 6],
[1, 0, 7, 9, 3, 2, 5, 8, 6, 4],
[2, 0, 6, 3, 4, 1, 5, 7, 9, 8],
[5, 6, 8, 3, 2, 0, 9, 4, 1, 7],
[3, 0, 1, 7, 9, 8, 2, 4, 6, 5],
[6, 2, 7, 8, 0, 9, 4, 1, 5, 3],
[9, 3, 1, 2, 0, 7, 5, 6, 8, 4],
[4, 1, 5, 9, 6, 7, 0, 2, 8, 3],
[6, 0, 1, 7, 2, 9, 5, 8, 4, 3]]
上面的算法的结果是这样
[(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 0), (6, 6), (7, 9), (8, 8), (9, 7)]
# 也就是0号男生配1号女生,以此类推。 说实话 我觉得结果甚至都有些重复。
我的版本
# 把自己带入 非成勿扰 录制现场
def gs_matching(man_preferences, woman_preferences):
length = len(man_preferences)
is_man_dated = [False] * length # 10位男嘉宾是否已经撩到妹妹了
is_woman_dated = [False] * length # 10位美人是否已经名花有主
result = [-1] * length
while False in is_man_dated:
new_man = is_man_dated.index(False)
girls_he_likes = man_preferences[new_man] # 康康这个男生最喜欢谁
for girl in girls_he_likes:
# 查看女生是否已经被约
if is_woman_dated[girl] is False: #发现没有,那就当场拿下
result[new_man] = girl
is_woman_dated[girl] = True
is_man_dated[new_man] = True
break # 换下一个男嘉宾登场,进行选择
else:
# 女嘉宾已经心有所属,现在进入权利反转环节, 女生对两位男嘉宾进行挑选
current_boyfriend = result.index(girl)
if woman_preferences[girl].index(current_boyfriend) > woman_preferences[girl].index(new_man):
# 看看是不是更喜欢 新来的这个小鲜肉,如果是,果断甩掉之前的蓝朋友
is_man_dated[current_boyfriend] = False
result[current_boyfriend] = -1
is_man_dated[new_man] = True
result[new_man] = girl
break # 换下一个男嘉宾登场,进行选择
print(result)
我的这个算法的结果是这样的
[1, 2, 3, 4, 5, 0, 6, 9, 8, 7]
# 结果数据的index虽然没显示出来,但是也代表意义。
# 结果数组的第0号位置,就代表0号男生配对1号女生, 以此类推。
区别
首先说,两个代码都可以正确的运行,获得稳定匹配的结果。
但是我的代码使用更小,更少的变量。
更少的数据交换。
也更符合“延迟接受”算法的含义。