【算法】稳定匹配(C++版)

由于学习需要,然后花费将近两天时间研究这个问题,然后用C++描述出来,具体内容看下面:

问题描述(见百度百科):
https://baike.baidu.com/item/%E7%A8%B3%E5%AE%9A%E5%A9%9A%E5%A7%BB%E9%97%AE%E9%A2%98/12760040

为了解决稳定匹配问题(Stable Matching Problem),前辈们提出了GS算法。

下面就是博主使用GS算法完成的本题,同时在研究过程中发现了一个新的匹配思路,将会在下面发出来(不知道前辈们有没有提出过),大家可以积极提出宝贵意见:

问题分析:

1.首先输入男士(女士)人数,这里男士,女士人数相同并且要求最后每个人都有对象。

2.初始化所有男士,女士追求过对象人数better=0,对异性喜欢排名数组rank[],当前是否在约会状态Yuehui,以及现任为-1;

3.既然男的需要主动,那就让所有单身状态的男士向自己最喜欢的女士表白,不管结局成功与否,该男士追求过的人数都加1;

4.如果女士单身,那么两个人就暂时在一起先处着,更改两个人是否约状态为true,设置对方为自己的现任;

5.如果女士不是单身,此时就出现了小三,那么主动权就交给女士了,此时女士比较现任小三,如果更喜欢现任。跳过当前追求者;如果更喜欢小三,抛弃现任,此时小三终于扬眉吐气成功上位,并与当前追求者结合成暂时情侣去约会。

6.判断是否全部找到对象,都找到了结束查找,否则重复步骤:2-5,直到全部由对象;

7.结束,输出;

程序设计
这里使用历史人物,(得到的最终匹配结果可能不与现实相同),男女各5名,对其进行编号。由编号代替其姓名。
这里写图片描述

各男士喜欢排名表:
(仅供实验参考,最终数据为自行输入)
这里写图片描述
各女士喜欢排名表:
(仅供实验参考,最终数据为自行输入)
这里写图片描述

定义人类(是人 ):

//人类
class People
{
    private:
        int better;             //追求过几位女生
        int rank[NUM];          //喜欢排名
        bool Yuehui;            //是否在约会
        int present;            //现任
    public:
        People()
        {
            better = 0;
            Yuehui = false;
            present = -1;
        }
        void setRank(int mRank, int i);
        int getRank(int i) { return rank[i]; };
        void setYuehui(bool mYuehui);
        bool getYuehui() { return Yuehui; };
        void setBetter(int mBetter);
        int getBetter() { return better; };
        void setPresent(int mPressent);
        int getPressent() { return present; };
};

完整代码:

#include<iostream>
#include<cstring>
using namespace std;

const int NUM = 5;
int flag = 0;


//人类
class People
{
    private:
        int better;             //追求过几位女生
        int rank[NUM];          //喜欢排名
        bool Yuehui;            //是否在约会
        int present;            //现任
    public:
        People()
        {
            better = 0;
            Yuehui = false;
            present = -1;
        }
        void setRank(int mRank, int i);
        int getRank(int i) { return rank[i]; };
        void setYuehui(bool mYuehui);
        bool getYuehui() { return Yuehui; };
        void setBetter(int mBetter);
        int getBetter() { return better; };
        void setPresent(int mPressent);
        int getPressent() { return present; };
};
void People::setRank(int mRank, int i)
{
    rank[i] = mRank;
}
void People::setYuehui(bool mYuehui)
{
    Yuehui = mYuehui;
}
void People::setBetter(int mBetter) 
{
    better = mBetter;
}
void People::setPresent(int mPressent)
{
    present = mPressent;
}


int main()
{
    People man[NUM];
    People lady[NUM];
    for (int i = 0; i < NUM; i++)
    {
        for (int j = 0; j < NUM; j++)
        {
            int temp;
            cout << "请输入第" << i+1 << "个人喜欢的第" << j+1 << "个人:";
            cin >> temp;
            man[i].setRank(temp, j);
        }
    }
    cout << "男士初始化完毕" << endl;
    for (int i = 0; i < NUM; i++)
    {
        for (int j = 0; j < NUM; j++)
        {
            int temp;
            cout << "请输入第" << i + 1 << "个人喜欢的第" << j + 1 << "个人:";
            cin >> temp;
            lady[i].setRank(temp, j);
        }
    }
    cout << "女士初始化完毕" << endl;


    while (true)
    {
        flag = 1;                                       //设定全部脱单标记
        //所有男士向自己最喜欢的女士表白
        for (int i = 0; i < NUM; i++)
        {
            if (man[i].getYuehui() == false)            //男士单身
            {
                flag = 0;                               //还有单身狗标记
                int num_Y = man[i].getBetter();                 //男士应向第几位喜欢的表白
                int girl = man[i].getRank(num_Y);               //获取喜欢女士的位置
                man[i].setBetter(num_Y + 1);                    //无论表白失败与否,下次表白对象位置
                if (lady[girl].getYuehui() == false)    //喜欢的女士单身
                {
                    man[i].setYuehui(true);                 //男士改为约会状态
                    man[i].setPresent(girl);                //设置现任为该女士
                    lady[girl].setYuehui(true);             //喜欢的女士也更改为约会状态
                    lady[girl].setPresent(i);               //设置现任为该男士
//                  cout << girl<<" ";                      //输出最喜欢的女士
                }
                if (lady[girl].getYuehui() == true) //喜欢的女士不单身
                {
                    //女士通过比较与自己最喜欢的那位男士在一起
                    int before, now;
                    //通过循环判断现任和小三在女士心中的位置
                    for (int j = 0; j < NUM; j++)
                    {
                        if (lady[girl].getRank(j) == i)
                        {
                            now = j;
                        }
                        if (lady[girl].getRank(j) == lady[girl].getPressent())
                        {
                            before = j;
                        }
                    }
                    //如果女士喜欢现任
                    if (before < now)
                    {
                        //小三滚蛋吧~~
                        //man[i].setBetter(man[i].getBetter() + 1);
                    }
                    //女士喜欢
                    else if (before>now)
                    {
                        man[lady[girl].getPressent()].setYuehui(false); //现任变前任
                        man[lady[girl].getPressent()].setPresent(100);  //变单身狗
                        man[i].setYuehui(true);                         //小三上位
                        man[i].setPresent(girl);

                        lady[girl].setPresent(i);
                    }
                }
            }
        }

        if (flag == 1)
        {
            break;
        }   
    }
    //输出
    for (int i = 0; i < NUM; i++)
    {
        cout << i << "和" << man[i].getPressent() << "在一起" << endl;
    }
}

最后,看下结果吧~~
这里写图片描述

最最后,画了张图并结合上面三张表述我的新思路:
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

最最最后,感谢你的访问,有问题欢迎提出。

Tony-Chen
2017.10.25

心的强大因为鉴定!

稳定匹配问题是一个经典的算法问题,其中Gale-Shapley算法是一种常用的解决方案。下面我简要介绍如何使用C语言编写程序来求解稳定匹配问题。 首先,我们需要定义一个结构体来表示每个人的偏好列表和当前匹配状态。偏好列表可以用整数数组来表示,数组的索引表示其他人的编号,数组的值表示对这个人的偏好等级。例如,假设有n个人,我们可以定义一个结构体如下: ```c typedef struct { int n; // 人数 int **preference; // 偏好列表 int *matching; // 当前匹配 } MatchingProblem; ``` 然后,我们可以使用如下的Gale-Shapley算法来求解稳定匹配问题: 1. 初始化所有人的匹配状态为空。 2. 循环直到没有人再能够改变匹配状态为止: a. 对于每个未匹配的人,选择他偏好列表中的下一个候选人,记为当前候选人。 b. 如果当前候选人未匹配,则直接将其与该人匹配。 c. 如果当前候选人已经匹配,判断当前候选人是否更优于当前匹配。如果是,将当前匹配与当前候选人匹配,将原先与当前候选人匹配的人重新放回未匹配状态。 3. 输出每个人的匹配结果。 在C语言中,我们可以使用指针和动态内存分配来操作偏好列表和当前匹配状态。具体实现可以参考下面的伪代码: ```c void gale_shapley(MatchingProblem *problem) { int *proposals = malloc(sizeof(int) * problem->n); // 存储每个人的偏好索引 int *acceptances = malloc(sizeof(int) * problem->n); // 存储每个人的匹配状态 // 初始化匹配状态和偏好索引 for (int i = 0; i < problem->n; i++) { acceptances[i] = -1; // -1表示未匹配状态 proposals[i] = 0; // 初始化偏好索引为0 } while (1) { // 查找未匹配的人 int unmatched = -1; for (int i = 0; i < problem->n; i++) { if (acceptances[i] == -1) { unmatched = i; break; } } if (unmatched == -1) { // 所有人都已匹配 break; } // 获取当前候选人 int current = problem->preference[unmatched][proposals[unmatched]]; proposals[unmatched]++; if (acceptances[current] == -1) { // 当前候选人未匹配 acceptances[current] = unmatched; acceptances[unmatched] = current; } else if (problem->preference[current][unmatched] < problem->preference[current][acceptances[current]]) { // 当前候选人更优 acceptances[acceptances[current]] = -1; // 原来的匹配放回未匹配状态 acceptances[current] = unmatched; acceptances[unmatched] = current; } } // 输出匹配结果 for (int i = 0; i < problem->n; i++) { printf("Person %d is matched with Person %d\n", i, acceptances[i]); } free(proposals); free(acceptances); } ``` 通过以上的程序,我们可以使用Gale-Shapley算法来求解稳定匹配问题。该算法具有良好的时间复杂度,并且可以保证返回的匹配结果是稳定的。希望这个回答可以帮助你理解如何使用C语言编写程序来求解稳定匹配问题。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值