IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 匹配算法——相亲男女匹配 -> 正文阅读

[数据结构与算法]匹配算法——相亲男女匹配

时间:20210928

背景:有个相亲活动,需要暗地里给男女进行匹配,毕竟明面上直接说不喜欢哪个异性总是尴尬的。匹配的话,方法众多,并不能让每个人都满意,根据各自的意向,总能计算整体意向都不错的。


太长了不看,直接操作:

线下让N对男女:

  1. 写个小纸条,各自给N个异性排序,更喜欢的排在前面
  2. 得到:
    1. 女生的选择:womanChoices
      1. 女1:男2,男5,男1,....
      2. 女2:...
      3. ...
      4. 女N:...
    2. 男生的选择:manChoices
      1. 同理

操作:

  1. 进入网站:代码在线运行 - 在线工具
  2. 选择python
    1. 不要用python3
  3. 代码复制进去
  4. 修改代码里的两个变量:womanChoices、manChoices
    1. 将之前线下统计得到的,放在对应位置

  5. 点击“执行Run”
  6. 右侧出结果即可


?

算法:GS算法(盖尔-沙普利算法(Gale-Shapley algorithm))

算法思想:略

算法伪代码:

0ada99de85afd017f4e27d298fba153b.png


样例解释:

1、1对男女,不考虑

2、两对男女,分别优秀男1、一般男2;优秀女1、一般女2(“优秀”、“普通”方便理解,换成“青菜”、“萝卜”一个意思)

1.0、优秀女、男互相看中,普通女、男互相看中

  • 女1喜欢:男1>男2
  • 女2喜欢:男2>男1
  • 男1喜欢:女1>女2
  • 男2喜欢:女2>女1
  • 结果:男1——女1、男2——女2分别匹配
  • 解释:萝卜青菜各有所爱,分别各自找到自己最中意的

2.1.1、两女争优秀男,两男争优秀女

  • 女1喜欢:男1>男2
  • 女2喜欢:男1>男2
  • 男1喜欢:女1>女2
  • 男2喜欢:女1>女2
  • 结果:优秀男1——优秀女1、一般男2——一般女2
  • 解释:优者则优

2.2.1、两女争优秀男,两男争普通女

  • 女1喜欢:男1>男2
  • 女2喜欢:男1>男2
  • 男1喜欢:女2>女1
  • 男2喜欢:女2>女1
  • 结果:优秀男1——普通女2、普通男2——优秀女1
  • 解释:
    • 两男争普通女,该普通女不普通,优先级高,是个“优秀女”,优秀男1同理,故两个被相争的在一起
    • 该情况和上面一种“两女争优秀男,两男争优秀女”是类似

2.1.2、两女争普通男,两男争普通女:换身份,转换为“两女争优秀男,两男争优秀女”情况一样,

2.2.2、两女争普通男,两男争优质女:换身份,转换为“两女争优秀男,两男争普通女”情况一样

3.1.1、两女争优秀男,优秀男争优秀女、普通男争普通女

  • 女1喜欢:男1>男2
  • 女2喜欢:男1>男2
  • 男1喜欢:女1>女2
  • 男2喜欢:女2>女1
  • 结果:优秀男1——优秀女1、一般男2——一般女2
  • 解释:普通男1没被优秀女1优先选。

3.2.1、两女争优秀男,优秀男争普通女、普通男争优秀女

  • 结果:优秀男1——普通女2、普通男2——优秀女1
  • 解释:和3.1.1情况类似,优秀男权重更高(被两女相争)

3.1.2、两女争普通男,普通男争优秀女、优秀男争普通女

  • 解释:和3.1.1情况类似,普通男、优秀男身份互换即可

3.2.2、两女争普通男,普通男争普通女、优秀男争优秀女

  • 解释:和3.2.1情况类似,普通男、优秀男身份互换;

4、四角恋:女1->男1->女2->男2->女1

  • 女1喜欢:男1>男2
  • 女2喜欢:男2>男1
  • 男1喜欢:女2>女1
  • 男2喜欢:女1>女2
  • 结果:
    • 女士优先时:女1——男1、女2——男2
    • 男士优先时:女2——男1、女1——男2

代码:

# coding:utf-8
"""
Demo of Gale-Shapley stable marriage algorithm.

Usage is:
   python marriage.py  [menfile]  [womenfile]

or

   python marriage.py  [menfile]  [womenfile]  V

for verbose mode.

For simplicity, the file format is assumed (without checking) to match
the following format:

  bob:     alice,carol
  david:   carol,alice

and likewise for the womenfile, where there should be precisely same
number of men as with women, and the identifiers should be
self-consistent between the two files.
"""
import sys

# 原作者的例子:
womanChoices = '''
W:       D,B,C,A
X:       D,B,A,C
Y:       A,D,B,C
Z:       B,A,D,C
'''
manChoices = '''
A:      W,X,Z,Y
B:      W,Y,Z,X
C:      X,W,Y,Z
D:      W,Z,X,Y
'''

# 1.0、优秀女、男互相看中,普通女、男互相看中
womanChoices = '''
女1:男1,男2
女2:男2,男1
'''
manChoices = '''
男1:女1,女2
男2:女2,女1
'''

# 2.1.1、两优秀女争两优秀男、两优秀男争两优秀女
womanChoices = '''
女1:男1,男2
女2:男1,男2
'''
manChoices = '''
男1:女1,女2
男2:女1,女2
'''

# 3.1.1、两女争优秀男,优秀男争优秀女、普通男争普通女
womanChoices = '''
女1:男1,男2
女2:男1,男2
'''
manChoices = '''
男1:女1,女2
男2:女2,女1
'''

# 4、四角恋:女1->男1->女2->男2->女1
womanChoices = '''
女1:男1,男2
女2:男2,男1
'''
manChoices = '''
男1:女2,女1
男2:女1,女2
'''
# ---------------------------------------------------------------------------------------
# 现场活动男女们的选择:(格式类似上面的,一人一行,冒号、逗号注意)
# 女生
womanChoices = '''

'''

# 男生选择的结果:放这里
manChoices = '''

'''
# ---------------------------------------------------------------------------------------

class Person:
    """
    Represent a generic person
    """

    def __init__(self, name, priorities):
        """
        name is a string which uniquely identifies this person

        priorities is a list of strings which specifies a ranking of all
          potential partners, from best to worst
        """
        self.name = name
        self.priorities = priorities
        self.partner = None

    def __repr__(self):
        return 'Name is ' + self.name + '\n' + \
               'Partner is currently ' + str(self.partner) + '\n' + \
               'priority list is ' + str(self.priorities)


class Man(Person):
    """
    Represents a man
    """

    def __init__(self, name, priorities):
        """
        name is a string which uniquely identifies this person

        priorities is a list of strings which specifies a ranking of all
          potential partners, from best to worst
        """
        Person.__init__(self, name, priorities)
        self.proposalIndex = 0                   # next person in our list to whom we might propose

    def nextProposal(self):
        goal = self.priorities[self.proposalIndex]
        self.proposalIndex += 1
        return goal

    def __repr__(self):
        return Person.__repr__(self) + '\n' + \
            'next proposal would be to ' + self.priorities[self.proposalIndex]


class Woman(Person):
    """
    Represents a woman
    """

    def __init__(self, name, priorities):
        """
        name is a string which uniquely identifies this person

        priorities is a list of strings which specifies a ranking of all
          potential partners, from best to worst
        """
        Person.__init__(self, name, priorities)

        # now compute a reverse lookup for efficient candidate rating
        self.ranking = {}
        for rank in range(len(priorities)):
            self.ranking[priorities[rank]] = rank

    def evaluateProposal(self, suitor):
        """
        Evaluates a proposal, though does not enact it.

        suitor is the string identifier for the man who is proposing

        returns True if proposal should be accepted, False otherwise
        """
        return self.partner == None or self.ranking[suitor] < self.ranking[self.partner]


def parseFileOld(filename):
    """
    Returns a list of (name,priority) pairs.
    """
    people = []
    f = file(filename)
    for line in f:
        pieces = line.split(':')
        name = pieces[0].strip()
        if name:
            priorities = pieces[1].strip().split(',')
            for i in range(len(priorities)):
                priorities[i] = priorities[i].strip()
            people.append((name, priorities))
    f.close()
    return people


def parseFile(choices):
    choices = choices.replace(':', ':')
    choices = choices.replace(',', ',')
    people = []
    for line in choices.split('\n'):
        pieces = line.split(':')
        name = pieces[0].strip()
        if name:
            priorities = pieces[1].strip().split(',')
            for i in range(len(priorities)):
                priorities[i] = priorities[i].strip()
            people.append((name, priorities))
    return people


def printPairings(men):
    for man in men.values():
        print man.name, 'is paired with', str(man.partner)


def main_old():
    verbose = len(sys.argv) > 3

    # initialize dictionary of men
    menlist = parseFile(sys.argv[1])
    men = dict()
    for person in menlist:
        men[person[0]] = Man(person[0], person[1])
    unwedMen = men.keys()

    # initialize dictionary of women
    womenlist = parseFile(sys.argv[2])
    women = dict()
    for person in womenlist:
        women[person[0]] = Woman(person[0], person[1])

    ############################### the real algorithm ##################################
    while unwedMen:
        m = men[unwedMen[0]]             # pick arbitrary unwed man
        w = women[m.nextProposal()]      # identify highest-rank woman to which
        #    m has not yet proposed
        if verbose:
            print m.name, 'proposes to', w.name

        if w.evaluateProposal(m.name):
            if verbose:
                print '  ', w.name, 'accepts the proposal'

            if w.partner:
                # previous partner is getting dumped
                mOld = men[w.partner]
                mOld.partner = None
                unwedMen.append(mOld.name)

            unwedMen.remove(m.name)
            w.partner = m.name
            m.partner = w.name
        else:
            if verbose:
                print '  ', w.name, 'rejects the proposal'

        if verbose:
            print "Tentative Pairings are as follows:"
            printPairings(men)
            print

    # we should be done
    print "Final Pairings are as follows:"
    printPairings(men)


def main(manChoices, WomanChoices):
    # initialize dictionary of men
    menlist = parseFile(manChoices)
    men = dict()
    for person in menlist:
        men[person[0]] = Man(person[0], person[1])
    unwedMen = men.keys()

    # initialize dictionary of women
    womenlist = parseFile(WomanChoices)
    women = dict()
    for person in womenlist:
        women[person[0]] = Woman(person[0], person[1])

    ############################### the real algorithm ##################################
    while unwedMen:
        m = men[unwedMen[0]]             # pick arbitrary unwed man
        w = women[m.nextProposal()]      # identify highest-rank woman to which
        #    m has not yet proposed
        if w.evaluateProposal(m.name):
            if w.partner:
                # previous partner is getting dumped
                mOld = men[w.partner]
                mOld.partner = None
                unwedMen.append(mOld.name)

            unwedMen.remove(m.name)
            w.partner = m.name
            m.partner = w.name
    #####################################################################################

    # we should be done
    print "Final Pairings are as follows:"
    printPairings(men)


if __name__ == "__main__":
    # 女士优先,womanChoices放前面, 否则放后面
    main(womanChoices, manChoices)

作者源代码:


参考资料:

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-09-29 10:33:19  更:2021-09-29 10:34:05 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 5:36:51-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码