poj 3487 zoj 3120 The Stable Marriage Problem 延迟认可算法(Gale-Shapley算法)

/*
传说中的Gale-Shapley算法。。。
第一次听说这个算法
百度一下才知道此算法已经有其实际应用了。。。
此题从早上八点开始看
先是用了n多队列写
测试倒是通过了
就是提交时老SF
然后就看到了网上说的Gale-Shapley算法
从学习算法然后写代码调试
最后到提交AC时已经是下午4点半
本来以为今天肯定过不了
没先到提交时一次通过
喜悦之情顿生。。。 
不说废话了
下面讲一下思路:
该算法的总体思路是
让男生根据他们对女生的喜欢程度对女生进行追求
女生则根据前来追求的对象决定是接受还是拒绝
接受还是拒绝取决于该女生对该男生的喜欢程度 
具体实现是用两个矩阵
1. libman[][]记录男生喜欢的女生列表
从喜欢到不喜欢降序排列
2.ladyscore[][]记录女生对各个男生所打的分数
分数越高则表明女生对该男生的心仪程度越高 
男生有两种状态
自由男和约会男
我们的目标是让所有的自由男变成约会男
所以用一个栈freeman(队列亦可)装自由男
当栈空时表明约会结束
用数组man[]来记录对应编号的男生下一个约会目标
用数组lady[]来记录对应编号的女生现任男友的编号
为了便于处理
虚构一个不存在的男友,编号最大,分数最低
意即此人为某女生现任男友时只要有人追求
该女生就会毫不留情地抛弃他 
*/
#define LOCAL
#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm> //sort()包含在这个头文件中 ps:在大多数情况下sort()比qsort()要快 
#define N 26
using namespace std;
int main()
{
#ifdef LOCAL
       freopen("input.txt","r",stdin);
       freopen("output.txt","w",stdout);
#endif

    short ncase,couple,libman[N][N],man[N],ladyscore[N][N],lady[N],male,female,i,j,first=1,a[N];
    stack<int> freeman;
    string list;
    char temp;  
    cin>>ncase;
    while(ncase--)
    {
            if(first) first=0; 
            else cout<<endl;                 //打印实例间的空格 
            while(!freeman.empty())  freeman.pop(); //清空栈 
            cin>>couple;
            //得到数据 
            for(i=0;i<couple;i++)
            {
                   cin>>temp;
                   a[i]=temp-'a';   //用a[]记录男生列表 
                   freeman.push(a[i]);   //所有男生(一开始都是自由男)入栈                  
            }  
            sort(a,a+couple);//对所有输入的男生进行排序一边与后面按字典序输出 
            for(i=0;i<couple;i++) cin>>temp;
            //接收女生列表(由于女生和男生是一一对应的所以这里只是将其接收而并不记录) 
            for(i=0;i<couple;i++)//记录男生的心仪女生 
            {
                   cin>>list;
                   for(j=0;j<couple;j++)
                   {
                           libman[i][j]=list[j+2]-'A';                     
                   }                     
            }            
            for(i=0;i<couple;i++)//女生对他们的追求者一一打分 
            {
                   cin>>list;
                   for(j=0;j<couple;j++)
                          ladyscore[i][list[j+2]-'a']=couple-j;              
            }            
            for(i=0;i<couple;i++)
                   ladyscore[i][couple]=0;//对"不存在"的男生打最低分 
            memset(man,0,sizeof(man));
            for(i=0;i<N;i++)  lady[i]=couple;//这里不能用memset()因为couple是变量而不是常数 
            while(!freeman.empty())//进行匹配 
            {
                     male=freeman.top();//用male记录当前追求者 
                     female=libman[male][man[male]];//用female记录male所追求的女生 
                     if(ladyscore[female][male]>ladyscore[female][lady[female]]) //若当前追求者比其现任男友优秀 
                     {
                              freeman.pop();//该男生约会成功跳出自由男行列 
                              if(lady[female]!=couple)//如果该女生有前男友 
                              {freeman.push(lady[female]);man[lady[female]]++;}
                              //将其前男友打入自由男行列,该男生刻意追求他的次喜欢女生 
                              lady[female]=male;//追求者成为该女生现任男友 
                     }                      
                     else if(ladyscore[female][male]<ladyscore[female][lady[female]]) //若当前追求者没有其现任男友优秀 
                              man[male]++;//该男生可以追求其次喜欢女生 
            }
            for(i=0;i<couple;i++) //输出约会结果 
                     printf("%c %c\n",a[i]+'a',libman[a[i]][man[a[i]]]+'A');
                               
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值