//题意:(稳定婚姻问题)尽量找男对女,女对男好感度都比较高的配对
举个反例:现在男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+10
typedef 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,一般用队列实现
//如果男孩追过一个女孩,后来被甩了,再去匹配的时候就不用再追这个女孩了
//但这个剪枝这里没用,这题很水,怎么都能过QAQ
void 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;
}