• [python3]稳定匹配算法实现和优化


    问题的描述

    在这里就不赘述了,你能搜到这篇文章,那肯定知道只算法的背景是啥

    解决思路

    1. 男生向还未拒绝其的女生中选出优先级最高的,并向其求婚
    2. 女生如果没有已经被优先级更高的男生求婚,则答应(女生以后可以反悔)。 如果反之,则拒绝
    3. 对此步骤进行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号女生, 以此类推。
    

    区别

    首先说,两个代码都可以正确的运行,获得稳定匹配的结果。
    但是我的代码使用更小,更少的变量。
    更少的数据交换。
    也更符合“延迟接受”算法的含义。

  • 相关阅读:
    【转】Unity学习笔记——MonoBehaviour类Invoke, Coroutine
    【转】Unity3D协同程序(Coroutine)
    Java定时任务
    SMSLib开发指南
    短信猫JAVA二次开发包SMSLib,org.smslib.TimeoutException: No response from device解决方案
    注解+反射+JDBC,实现一个简易的泛型DAO接口
    利用Window超级终端,修改短信猫波特率
    深入理解JDK动态代理机制
    深入分析Java ClassLoader原理
    Linux内核升级指南
  • 原文地址:https://www.cnblogs.com/sight-tech/p/13187309.html
Copyright © 2020-2023  润新知