Marriage is Stable

来源:互联网 发布:网络市场监管专项行动 编辑:程序博客网 时间:2024/06/16 11:57

这里写图片描述

这里写图片描述

//题意:(稳定婚姻问题)尽量找男对女,女对男好感度都比较高的配对
举个反例:现在男A和女a是情侣,如果男B也喜欢女a,而女a也更喜欢男B,那么男B和女a就很可能好上了,给男A戴绿帽子,所以这种婚姻是不稳定的。

//思路:Gale-Shapley算法

算法介绍:

1.先给男生心目中对女生的好感度排个序,同理,也给女生心目中对男生的好感度排。

2.男生去追女生(男的当然应该主动点),每个男生按好感顺序(好->差)去追女生。

1)若女生现在还没男朋友,两人就先配对,去约会了。

2)若女生有男朋友了,但对这个男生的好感度比对她男朋友的好感度还要高,那么就果断甩了男朋友,跟现在这个男生在一起。(心疼被戴绿帽子的男生一秒)之前那个男生回归单身。

3)循环重复1)2)直到所有男女都配对成功
注:如果男生之前被这个女生甩过,就不用再去追她了,因为那个女生对她男朋友的好感度肯定比他高(就是因为这样才被甩的…)

还有,稳定婚姻问题必然有解,美国数学家David Gale和Lloyd Shapley已经证明过了。

#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <cstdlib>#include <cmath>#include <ctime>#include <algorithm>using namespace std;#define MAX 500+10typedef struct {    char name[30];  //名字    char Love[MAX][30];  //按对异性的好感程度存放的异性名字    bool is_date; //是否已经和异性在约会}Person;int n;Person B[MAX], G[MAX]; //B:boy  G:girl //男的心目中对女的好感程度的排名 //前[]:男孩的编号  后[]:好感度   //B_G[][]:女孩的编号int B_G[MAX][MAX];//女的心目中对男的好感程度的排名//前[]:女孩的编号  后[]:男孩的编号//G_B[][]:好感度int G_B[MAX][MAX]; int man[MAX]; //男孩的匹配对象int women[MAX]; //女孩的匹配对象//寻找名字是str的女孩的编号int findboy(char str[]){    for (int i = 1; i <= n; i++)    {        if (strcmp(str, G[i].name) == 0)            return i;    }}//寻找名字是str的男孩的编号int findgirl(char str[]){    for (int i = 1; i <= n; i++)    {        if (strcmp(str, B[i].name) == 0)            return i;    }}//给B_G[][]赋值//女孩在男孩心目中的排名void BoyRank(){    int i, j;    for (i = 1; i <= n; i++)    {        for (j = 1; j <= n; j++)        {            B_G[i][j] = findboy(B[i].Love[j]);        }    }}//给G_B[][]赋值//男孩在女孩心目中的排名void GirlRank(){    int i, j;    for (i = 1; i <= n; i++)    {        for (j = 1; j <= n; j++)        {            G_B[i][findgirl(G[i].Love[j])] = j;        }    }}//Gale-Shapley算法//介绍见思路//循环实现是便于理解,这样很容易TLE,一般用队列实现//如果男孩追过一个女孩,后来被甩了,再去匹配的时候就不用再追这个女孩了//但这个剪枝这里没用,这题很水,怎么都能过QAQvoid GS(){    int i, j, ok = 1;    memset(man, 0, sizeof(man));    memset(women, 0, sizeof(women));    //要进行到所有男孩都找到女朋友为止    while (ok == 1)    {        ok = 0;        for (i = 1; i <= n; i++)        {            if (man[i] == 0)            {                ok = 1;                for (j = 1; j <= n; j++)                {                    //该女孩现在的男朋友的编号                    int womenpos = women[B_G[i][j]];                     //若这个女孩还没有男朋友,两人就直接配对                    if (G[B_G[i][j]].is_date == false)                    {                        man[i] = B_G[i][j];                        women[B_G[i][j]] = i;                        G[B_G[i][j]].is_date = true;                        break;                    }                    //若女孩对这个男孩更有好感,就甩了之前那个男的                    //和现在这个男的配对,之前那个男的回归单身                    else if (G_B[B_G[i][j]][i] < G_B[B_G[i][j]][womenpos])                    {                        man[womenpos] = 0;                        man[i] = B_G[i][j];                        women[B_G[i][j]] = i;                        break;                    }                }            }        }    }}int main(){    int i, j;    while (scanf("%d", &n) != EOF)    {        //输入        for (i = 1; i <= n; i++)        {            scanf("%s", B[i].name);            for (j = 1; j <= n; j++)            {                scanf("%s", B[i].Love[j]);            }        }        for (i = 1; i <= n; i++)        {            scanf("%s", G[i].name);            for (j = 1; j <= n; j++)            {                scanf("%s", G[i].Love[j]);            }        }        //预处理:先把所有男孩、女孩都设为没有约会的状态        for (i = 1; i <= n; i++)        {            B[i].is_date = false;            G[i].is_date = false;        }        //好感度排序        BoyRank();        GirlRank();        GS();        //输出        for (i = 1; i <= n; i++)        {            printf("%s %s\n", B[i].name, G[man[i]].name);        }        printf("\n");    }    return 0;}
原创粉丝点击