• Stable Matching (Gale Sharpley Algorithm)


    稳定婚配问题:n个男生n个女生。当中每一个人都有自己心仪的列表。

    问怎样达成稳定的匹配(比方, b想B求婚,可是B已有的对象的优先级高于b,此时b的魅力不足以拆散B所处的那一对,即达到稳定状态。)

    (Gale_Shapley algorithm)整体策略:男士负责求婚,女士负责接受或者拒绝。


    题目原型: HDUOJ 1914 The Stable Marriage Problem  

    下面为数据生成函数,生成boys_rankings.txt 和 girls_rankings.txt

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <string>
    #include <sstream>
    #include <algorithm>
    #include <vector>
    #include <ctime>
    #include <fstream>
    
    using namespace std;
    
    vector<string> gen_boys(int number)
    {
        vector<string> result;
        for(int i = 0; i < number; i++){
            string boy = "B";
            string s;
            stringstream ss;
            ss << i;
            ss >> s;
            boy.append(s);
            result.push_back(boy);
        }
        return result;
    }
    
    vector<string> gen_girls(int number)
    {
        vector<string> result;
        for(int i = 0; i < number; i++){
            string boy = "G";
            string s;
            stringstream ss;
            ss << i;
            ss >> s;
            boy.append(s);
            result.push_back(boy);
        }
        return result;
    }
    
    vector<string> gen_ranking(vector<string> candidate)
    {
        random_shuffle(candidate.begin(), candidate.end());
        return candidate;
    }
    
    void write_rankings(vector<string> people, vector<vector<string> > rankings, string out_file)
    {
        ofstream ofs(out_file.c_str());
        if(ofs.fail()){
            cerr << "Error: " << out_file << endl;
            return;
        }
        for(int i = 0; i < people.size(); i++){
            ofs << people[i] << ":";
            for(int j = 0; j < rankings[i].size(); j++){
                ofs << " " << rankings.at(i).at(j);
            }
            ofs << endl;
        }
        ofs.close();
    }
    
    int main(int argc, char ** argv)
    {
        srand(time(NULL));
        int n = 200;
        vector<string> boys = gen_boys(n);
        vector<string> girls = gen_girls(n);
        vector<vector<string> > boys_rankings;
        vector<vector<string> > girls_rankings;
        for(int i = 0; i < n; i++){
            boys_rankings.push_back(gen_ranking(girls));
            girls_rankings.push_back(gen_ranking(boys));
        }
        write_rankings(boys, boys_rankings, "boys_rankings.txt");
        write_rankings(girls, girls_rankings, "girls_rankings.txt");
        return 1;
    }

    下面为Gale_Sharpley算法实现:

    /******************************************************
    *   Projects : Implementation of Gale_Shapley algorithm
    *   Author   : johnsondu
    *   Time     : 2014-10-20 21:18
    *******************************************************/
    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <fstream>
    #include <map>
    #include <vector>
    #include <cstring>
    #include <string>
    using namespace std;
    
    // The max size of the number of the boy.
    const int MAXN = 1000;
    // STL map, map boy's name to integer ID
    map<string, int> boy;
    // STL map, map girl's name to integer ID
    map<string, int> girl;
    // STL map, map corresponding boy's integer id to original string name
    map<int, string> boyName;
    // STL map, map corresponding girl's integer id to original string name
    map<int, string> girlName;
    // boy's preference ranking list
    int boysRankings[MAXN][MAXN];
    // girl's preference ranking list
    int girlsRankings[MAXN][MAXN];
    // the partner that boy matched. if no, marked as -1
    int boysPartner[MAXN];
    // the partner that girl matched. if no, marked as -1
    int girlsPartner[MAXN];
    
    /*******************************************************
    *  function description:
    *  let every boy and girl have it's own integer identity.
    *  key variable: <string, int>(map string name to integer
    *  id), <int, string>(map integer id to original string
    *  name)
    ********************************************************/
    void SerialNumber(int &n)
    {
        ifstream in1("boys_rankings.txt");
        ifstream in2("girls_rankings.txt");
        string str;
    
        int idb = 0;    // boy's id
        int idg = 0;    // girl's id
    
        while(getline(in1, str)){
            string name = "";
            int i = 0;
            // get boys's name
            while(str[i] != ':') name += str[i ++];
            // map string to int.
            boy[name] = idb ;
            boyName[idb] = name;
            idb ++;
            // get the number of boys.
            n ++;
        }
    
        while(getline(in2, str)){
            string name = "";
            int i = 0;
            // get boys's name
            while(str[i] != ':') name += str[i ++];
            // map string to int.
            girl[name] = idg;
            girlName[idg] = name;
            idg ++;
        }
        return;
    }
    
    /*********************************************
    *   function description:
    *   Rereading two files, and get corresponding
    *   preference list of boys and girls. Save it
    *   in two dimension array: girlsRankings and
    *   boysRankings.
    *******************************************/
    void GetRankings(const int n)
    {
        ifstream in1("boys_rankings.txt");
        ifstream in2("girls_rankings.txt");
        string str;
    
        // boy's id.
        int id = 0;
        while(getline(in1, str)){
            string gname;
            int i = 0;
    
            int cnt = 0;
            while(str[i] != ' ') i ++;
            if(str[i] == ' ') i ++;
            for(; i < str.size();)
            {
                gname = "";
                while(str[i] != ' ' && i < str.size()) {
                    gname += str[i];
                    i ++;
                }
                boysRankings[id][cnt ++] = girl[gname];
                if(str[i] == ' ') i ++;
            }
            id ++;
        }
    
        // girls id;
        id = 0;
    
        while(getline(in2, str)){
    
            string bname;
            // string size index.
            int i = 0;
            // the rankings in the girl's list.
            int cnt = 0;
            // prefix guarantee
            while(str[i] != ' ') i ++;
            if(str[i] == ' ') i ++;
            for(; i < str.size();)
            {
                bname = "";
                while(str[i] != ' ' && i < str.size()) {
                    bname += str[i];
                    i ++;
                }
                girlsRankings[id][cnt ++] = boy[bname];
                if(str[i] == ' ') i ++;
            }
            id ++;
        }
        return ;
    }
    
    /*************************************
    *   function description:
    *   set status for boys and girls,
    *   marked -1, no partner.
    **************************************/
    void InitStatus(const int n)
    {
        for(int i = 0; i < n; i ++)
        {
            boysPartner[i] = -1;
            girlsPartner[i] = -1;
        }
    }
    
    /****************************************
    *   function description:
    *   when one boy propose to one girl, and
    *   that girl already have a partner, this
    *   function is used for get ratings of
    *   two boys in that girl's preference list.
    *****************************************/
    int GetId(int boyId, int gId, const int n)
    {
        for(int i = 0; i < n; i ++)
        {
            if(girlsRankings[gId][i] == boyId) return i;
        }
        return -1;
    }
    
    /****************************************
    *   function description:
    *   once a man have dumped by a girl, set
    *   his status to no partner, and set his
    *   preference list of that girl as -1,
    *   stand for have been proposed before.
    *****************************************/
    void SetStatus(int boyId, int girlId, const int n)
    {
        boysPartner[boyId] = -1;
        for(int i = 0; i < n; i ++)
            if(boysRankings[boyId][i] == girlId){
                boysRankings[boyId][i] = -1;
                return;
            }
    }
    
    /****************************************
    *   function description:
    *   Implementation of Gale_Shapley algorithm
    *****************************************/
    void StableMatch(const int n)
    {
        InitStatus(n);
    
        while(true)
        {
            bool flag = false;
            bool endOfFor = false;
            // guarantee all the boys have a partner.
            for(int i = 0; i < n; i ++){
                if(boysPartner[i] == -1 || girlsPartner[i] == -1)
                {
                    flag = true;
                    break;
                }
            }
            if(!flag) break;
    
            // for boy who have no partner.
            for(int i = 0; i < n; i ++)
            {
                if(boysPartner[i] == -1){
                    for(int j = 0; j < n; j ++){
                        // Since in the list of preference, j had rejected before.
                        if(boysRankings[i][j] == -1) continue;
    
                        // if j have no partner, then accept.
                        if(girlsPartner[boysRankings[i][j]] == -1){
                            boysPartner[i] = boysRankings[i][j];
                            girlsPartner[boysRankings[i][j]] = i;
                            endOfFor = true;
                            break;
                        }
                        else{  // judge whether match is stable or not
                            int useId = GetId(girlsPartner[boysRankings[i][j]], boysRankings[i][j], n);
                            int curId = GetId(i, boysRankings[i][j], n);
                            // if not stable
                            if(curId < useId){
                                // girl's partner's list, set -1 to mean the girl have rejected.
                                SetStatus(girlsPartner[boysRankings[i][j]], boysRankings[i][j], n);
                                boysPartner[i] = boysRankings[i][j];
                                girlsPartner[boysRankings[i][j]] = i;
                                endOfFor = true;
                                break;
                            }
                        }
                    }
                }
                // find a partner, break out of the loop.
                if(endOfFor) break;
            }
        }
    }
    
    /****************************************
    *   function description:
    *   print out result.
    *****************************************/
    void Print(const int n)
    {
        freopen("result.txt", "w", stdout);
        cout << "The Matching Results are follows:" << endl;
        for(int i = 0; i < n; i ++){
            cout << boyName[i]
                << "--" << girlName[boysPartner[i]] << "  " << endl;
        }
    }
    
    /****************************************
    *   function description:
    *   Main function
    *****************************************/
    int main()
    {
        int n = 0;
        // let every boy and girl have it's own identity.
        // and get integer ranking array list.
        SerialNumber(n);
        // get rankings.S
        GetRankings(n);
        // Stable match
        StableMatch(n);
        // Print solution
        Print(n);
    
        return 0;
    }
    


  • 相关阅读:
    [FJOI2007]轮状病毒
    [SHOI2013]发微博
    ATCODER ABC 099
    [HEOI2015]兔子与樱花
    [TJOI2017]可乐
    [TJOI2015]线性代数
    [Ceoi2008]order
    [CTSC2008]祭祀river
    [POI2009]Lyz
    数列分块(数据结构)学习笔记
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/6985074.html
Copyright © 2020-2023  润新知