中興捧月杯第一題初賽

1、標題:java

    數字化婚姻配對嘗試ios

2、題目:c++

創建一個模型,來模擬推導社會男女擇偶過程。編程

爲了模型簡化,一我的的特性指標有三個,這裏假設爲財富、樣貌、品格,每一個指標都可取值1-100之間任意數字。一樣也對這3項指標有本身的需求。這3個需求值取值範圍都在1-98間,固然三者的和必須爲100.因此任意一我的能夠用如下數組來表述:windows

G(A、B、C、A一、B一、C1)G表明男,M表明女。數組

舉例G11(80、50、40、十、30、60),表示男11號,擁有財富80、樣貌50、品格40,對異性品格的偏好爲:財富在意程度百分之十、樣貌在意程度百分之30、品格在意程度百分之60。數據結構

一樣爲了模型簡化,假設信息是徹底對稱的,便是說,每一個人都能一眼就能看清楚任意一我的的財富、樣貌、品格。app

仍是爲了模型簡化,我建模所用樣本爲男女各100個,即男女人數相同。dom

每一個人對異性的滿意度將以下定義:每一個偏好指標與異性的對應的稟賦指標相乘,三個指標的乘積再相加,即他(她)對某個異性的滿意度。編程語言

舉例G11(80、50、40、十、30、60)對M(50、60、80、40、十、50)的滿意度爲:

(10*50+30*60+60*80)= 7100分

相對的 MM 對 GG的滿意度則爲:

(40*80+10*50+50*40) = 5700分

好了,配對活動開始,設計的配對法則以下:

一、100個男方,順序,輪流從0號到99號女方中挑選本身最滿意的一位,而後向她發出配對邀請。

二、接受邀請最多的女方開始行動,對這些邀請的男性中,選擇最滿意的一位。

三、那麼這兩位配對成功,剔除出樣本,剩下的99對繼續這樣配對。

四、循環該配對法則,直到最後一對男女配對成功。

3、初賽階段要求:

一、編程語言爲java,C++或C語言任意一種;運行環境windows。

二、能讓用戶輸入本身的參數以及對各項數值的偏好,而後隨機生成100位男性100位女性(包括用戶在內。若是用爲男性則爲99男100女),數值所有隨機但需知足題設限制。按照上述規則給出一個匹配結果呈現給用戶。

三、若採用c/c++,要輸出可執行程序;若採用java,給出jar和bat。

四、在匹配時,若是發現有多個滿意度相同的對象,要求自身三個屬性(財富,外貌,品格)總和大的優先,若是再相同則id小的優先。若是有2位女士的選票相同,優先級規則同上。請把主角的id置爲最小值,以便在前2個條件相同狀況下,主角能夠優先選擇。

五、程序讀取指定的配置文件,獲取樣本,而後根據指定的輸入,輸出結果。同時會給出一組源數據和標準答案給學生自測。最後再讓學生根據不一樣的,指定的輸入,給出考試答案。

  請點擊下載配置文件附件。附件中,male.txt,female.txt,players.txt 分別是男士樣本、女士樣本和主角樣本各 100位。 男女樣本中,每行都表明一位男士或女士的基本屬性,從左到右依次是ID, 樣貌,品格,財富 , 指望樣貌,指望品格,指望財富,沒有加入性別,須要在解析時手動添加,每一個txt文本的性別都是同樣的,請注意。另外,主角樣本中沒有ID屬性,換成了性別屬性,其中 0表示女性,1表示男性,其他屬性依次爲樣貌,品格,財富,指望樣貌 ,指望品格,指望財富。建議把主角的id都設置爲 -1,以便知足優先選擇的條件。

給出標準答案2組,用於考生自測:

1號主角(文本第一行),選擇的對象屬性爲(6,18,82,87,3,10)

2號主角(文本第二行),選擇的對象屬性爲(27,74,22,22,58,20)

同時要求考生輸出9號主角(0,72,55,53,8,87,5),19號主角(0,11,4,63,22,60,18),47號主角(1,19,8,21,1,53,46),83號主角(1,23,11,17,58,31,11),99號主角(1,26,66,1,78,11,11)以及100號主角(0,68,28,19,43,11,46)的選擇結果。

4、初賽階段審覈標準及評價細則

1. 功能分(40分)

若是學生最後答案錯誤,則該項得0分

若是答案正確,得40分

2. 代碼質量分(30分)

可讀性,整潔性,健壯性,可擴展性,封裝性

3. 用戶體驗(10分)

界面美觀,操做方便,有必要的信息提示

4. 代碼文檔質量(10分)

代碼清晰,易讀,註釋完整

5. 單元測試(10分)

關鍵函數或容易出錯部分應該有單元測試保證

 

#include <iostream>
#include <fstream>
#include <ostream>
#include <vector>
#include <algorithm>
#include <ctime>
#include <cstdlib>

using namespace std;

int M = 100; //表示匹配對數
//將人用類Person表示
struct Person{
    int sex;
    int id;
    int fortune;
    int appearance;
    int character;
    int wFortune;
    int wAppearance;
    int wCharacter;

    int matchID; //匹配id號
    int satisfyID; //當爲男性是指最滿意的對方id號,女性是指被邀請的數目
    bool match; //是否成功,true表示已配對,false表示沒有

    Person(int s=0, int i=-2, int f=0, int a=0, int c=0, int wf=0, int wa=0, int wc=0, int mi=0, int si=0, bool m=false):
    sex(s),id(i),fortune(f),appearance(a),character(c),
        wFortune(wf),wAppearance(wa),wCharacter(wc),matchID(mi),satisfyID(si),match(m){}
};

//爲了在匹配時能惟一肯定滿意度順序,定義了一個輔助類SatDegree用於重載">"運算符
struct SatDegree{
    int satD; //對對方的滿意度
    int sum3; //對方三個屬性的總和
    int id;   //對方的id號
    SatDegree(int sd = 0, int s3 = 0, int i = -2):satD(sd),
        sum3(s3), id(i){}
};

// 數據結構,男性、女性都按id+1依次存儲,至關於hash表
vector<Person> male(M+1);//男性數組
vector<Person> female(M+1);//女性數組

//測試
vector<vector<int> > satm2fM(M+1,vector<int>(M+1,0));
vector<vector<int> > satf2mM(M+1,vector<int>(M+1,0));
vector<vector<int> > invitedM(M+1,vector<int>(2,0));

//重載">"號,當滿意度相等時,其屬性總和大的較大,但都相等時,id號小的大
bool operator >(const SatDegree& sd1, const SatDegree& sd2)
{
    if (sd1.satD > sd2.satD)
        return true;
    else if (sd1.satD == sd2.satD)
        if (sd1.sum3 > sd2.sum3)
            return true;
        else if (sd1.sum3 == sd2.sum3)
            if (sd1.id <= sd2.id) //"=="號是考慮到本身同本身比較的狀況
                return true;
            else
                return false;
        else
            return false;
    else
        return false;
}

ostream& operator<<(ostream& os, const Person& p)
{
    return os << p.fortune 
              << ',' << p.appearance
              << ',' << p.character
              << ',' << p.wFortune
              << ',' << p.wAppearance
              << ',' << p.wCharacter;
}

istream& operator>>(istream& is, Person& p)
{
    char comma;
    return is >> p.id >> comma 
        >> p.fortune >> comma 
        >> p.appearance >> comma 
        >> p.character >> comma 
        >> p.wFortune >> comma 
        >> p.wAppearance >> comma 
        >> p.wCharacter;
}

int sum3(Person p)
{
    return p.fortune+p.appearance+p.character;
}

SatDegree satisfy(Person p1,Person p2)//不一樣性別的p1對p2的滿意度
{
    SatDegree SD;
    SD.satD = p1.wFortune*p2.fortune+p1.wAppearance*p2.appearance+p1.wCharacter*p2.character;
    SD.sum3 = p2.fortune+p2.appearance+p2.character;
    SD.id = p2.id;
    return SD;
}

void matching()//匹配過程
{
    int i = 0, j = 0, k = 0, l = 0, minID = M-1, //最小的未匹配的id號
        satM2FID = -2,  //男性最滿意的女性的id
        satF2MID = -2, //女性最滿意的男性的id
        invitedN = 0, //女性的被邀請數臨時變量
        matchedFID = -1, noMatchNo = M; //匹配成功的女性id號及配對數
    SatDegree m2f, f2m,//男性對女性的滿意度、女性對男性的滿意度
        satFD, satMD; //男性對女性的滿意度及女性對男性的滿意度的臨時變量

    //vector<int> atemp(M,-1), btemp(M,-1);

    for ( ; noMatchNo > 0; --noMatchNo)
    {
        //測試
        //cout << "匹配第" << noMatchNo << "隊狀況:" << endl;
        for (i = 0;  i<= M; ++i) //依次尋找未匹配男性i的最滿意id號及得到對應的女性邀請數目
        {
            if (!male[i].match && male[i].id >= -1) //male[0]存儲的是主角或者空,空時不處理
            {
                for (j = 0; j <= M; ++j)
                {
                    if (female[j].id < -1)//female[0]存儲的是主角或者空,空時不處理
                        continue;

                    m2f = satisfy(male[i],female[j]); satm2fM[i][j] = m2f.satD;
                    if (m2f > satFD && !female[j].match)
                    {
                        satM2FID = j-1; //id號是hash表序號-1
                        satFD = m2f;
                    }
                    //測試:
                    //cout << "男性id=" << i-1 << ",女性id=" << j-1 << ",對女性的滿意度" << m2f.satD << endl << endl;
                }
                ++female[satM2FID+1].satisfyID; //對應女性的被邀請數目加1
                male[i].satisfyID = satM2FID;
                satFD.satD = 0; satFD.sum3 = 0; satFD.id = -2; //重置臨時的男對女滿意度
                //測試:
                //if (noMatchNo == M)
                //    cout << "男性id=" << i-1 << ",最喜歡的女性id=" << satM2FID << endl;
            }
        }
        //測試
        //cout << endl << "尋找邀請數最多的女性:" << endl;

        for (k = 0; k <= M; ++k) //尋找邀請數最多的女性id
        {
            if (female[k].id < -1)//female[0]存儲的是主角或者空,空時不處理
                    continue;
            if (!female[k].match) //k的id不小於matchedFID
                if ((female[k].satisfyID > invitedN) ||//k的選票大於matchedID的
                    ((female[k].satisfyID == invitedN) && //k的選票等於matchedID的
                    (sum3(female[k]) > sum3(female[matchedFID+1]))))//k的屬性和大於matchedID的
                {
                    invitedN = female[k].satisfyID;
                    matchedFID = k-1;
                }
        }
        invitedM[M-noMatchNo][0] = matchedFID; invitedM[M-noMatchNo][1] = invitedN;
        //測試
        //cout << "邀請數最多的女性id=" << matchedFID << ",邀請數" << invitedN << endl
        //    << endl << "尋找匹配的男性:" << endl;
        invitedN = 0; //被邀請數臨時變量重置爲0


        for (l = 0; l <= M; ++l) //尋找匹配的男性
        {
            if (male[l].id < -1) //male[0]存儲的是主角或者空,空時不處理
                continue;
            f2m = satisfy(female[matchedFID+1],male[l]);satf2mM[matchedFID+1][l] = f2m.satD;
            if (male[l].satisfyID == matchedFID && !male[l].match
                && f2m > satMD)
            {
                satF2MID = l-1;
                satMD = f2m;
            }
        }
        //測試
        //cout << "匹配男性id=" << satF2MID << ",滿意度" << satMD.satD << endl;
        male[satF2MID+1].match = true;
        male[satF2MID+1].matchID = matchedFID;
        satMD = 0;satMD.sum3 = 0;satMD.id = -2;//重置臨時的女對男滿意度
        
        //測試
        //atemp[satF2MID] = satF2MID; btemp[matchedFID] = matchedFID;
        //cout << noMatchNo << "," << satF2MID << "," << matchedFID << endl;
        minID = M;
        for (k = 0; k <= M; ++k)//刪除未匹配的女性的邀請數且將matchedFID重置爲未匹配女性中的最小id號
        {
            if (female[k].id < -1)//female[0]存儲的是主角或者空,空時不處理
                    continue;
            if (!female[k].match && k !=matchedFID+1
                && female[k].satisfyID <= female[matchedFID+1].satisfyID)
            {
                female[k].satisfyID = 0;
                if ((k-1) < minID)
                    minID = k-1;
            }
        }
        female[matchedFID+1].match = true; //刪除匹配的女性
        female[matchedFID+1].matchID = satF2MID;
        matchedFID = minID;
    }
}

int random(int x)
{
    return rand()%x;
}

//隨機初始化一我的的屬性(ID除外)
Person randPerson()
{
    Person p;
    p.fortune = random(M)+1;
    p.appearance = random(M)+1;
    p.character = random(M)+1;
    p.wFortune = random(M-2)+1;
    p.wAppearance = random(M-p.wFortune)+1;
    p.wCharacter = M-p.wFortune-p.wAppearance;
    return p;
}

//隨機生成數據、初始化並將其保存到對應的hash表中
void generateData(Person user) 
{
    vector<int> randSort1(M), randSort2(M);
    Person p1, p2;
    int i = 0;
    ofstream ofs1, ofs2;
    
    
    //任意排列0-M之間的數
    for (i = 0; i<M; ++i)
    {
        randSort1[i] = i;
        randSort2[i] = i;
    }
    random_shuffle(randSort1.begin(),randSort1.end());
    random_shuffle(randSort2.begin(),randSort2.end());

    //隨機生成男性和女性數據
    ofs1.open("male1.txt",ios_base::out);
    ofs2.open("female1.txt",ios_base::out);
    for (i = 0; i<M; ++i)
    {
        p1 = randPerson();
        p1.sex = 1;p1.id = randSort1[i];
        if (1 == user.sex && 0 == randSort1[i]) //用戶是男性則將其替換爲生成的0號id數據
            p1 = user;
        male[p1.id+1] = p1;
        ofs1 << p1.id << "," << p1 << endl;
        
        p2 = randPerson();
        p2.sex = 0;p2.id = randSort2[i];
        if (1 == user.sex && 0 == randSort2[i]) //用戶是女性則將其替換爲生成的0號id數據
            p1 = user;
        female[p2.id+1] = p2;
        ofs2 << p2.id << "," << p2 << endl;
    }
    ofs1.close();
    ofs2.close();    
}

//讀入文本數據並初始化以及進行測試
void readData() 
{
    Person p1, p2;
    ifstream ifs1, ifs2;
    
    ifs1.open("male.txt",ios_base::in);
    ifs2.open("female.txt",ios_base::in);
    while((ifs1 >> p1) && (ifs2 >> p2))
    {
        male[p1.id+1] = p1; female[p2.id+1] = p2;
    }
    ifs1.close();
    ifs2.close();    
}

//將結果保存到文本文件中
void result()
{
    int i = 0, j = 0;
    ofstream ofs1, ofs2, ofs3, ofs4;
    ofs1.open("satm2fM.txt",ios_base::out); //保存男對女的滿意度矩陣
    ofs2.open("satf2mM.txt",ios_base::out); //保存女對男的滿意度矩陣
    ofs3.open("matched.txt",ios_base::out); //保存匹配結果
    ofs4.open("invitedM.txt",ios_base::out);//保存女性被邀請的最多的id號及次數
    for (i = 0; i <=M; ++i)
    {
        for (j = 0; j <= M; ++j)
        {
            ofs1 << satm2fM[i][j] <<",";
            ofs2 << satf2mM[i][j] <<",";
        }
        ofs1 << endl << endl;
        ofs2 << endl << endl;
    }
    
    for (i = 0; i <= M; ++i)
    {
        ofs3 << i << ":" << male[i].id <<"," << male[i].matchID << endl; 
        ofs4 << i << ":" << invitedM[i][0] <<"," << invitedM[i][1] << endl; 
    }
    ofs1.close();
    ofs2.close();
    ofs3.close();
    ofs4.close();
}
//程序開始
void startProg()
{
    char ch, //用於接收用戶選項:是想測試仍是直接計算
        E = 'n', //用於接收用戶輸入:是否退出程序
        comma;
    int line = 0; //指定讀入的行
    Person user;
    ifstream ifs;

    cout << "===========數字化婚姻配對嘗試仿真程序===========" << endl;
    cout << "主角的信息包括:性別,樣貌,品格,財富,指望樣貌,指望品格,指望財富:" << endl
        << "輸入時請按該要求依次輸入主角信息!" << endl
        << "示例1:1,80,5,29,25,62,13;示例2:0,1,99,78,84,14,2" << endl;
    cout << "您是想測試用例仍是本身輸入數據進行計算?(測試輸入T/t,計算輸入C/c)" << endl;
    cin >> ch;
    if ('T' == ch || 't' == ch)//測試
    {
        ifs.open("players.txt",ios_base::in);
        ifs.seekg(0,ifs.end);
        int line_lenght = ifs.tellg()/M; //計算players.txt文件每一行的長度
        while (E != 'Y' && E != 'y')
        {
            readData();
            cout << "請輸入所給用戶示例文件players.txt中主角所在的行數:";
            cin >> line;
            ifs.seekg((line-1)*line_lenght,ifs.beg);
            ifs >> user.sex >> comma >> user.fortune >> comma >> user.appearance
                >> comma >> user.character >> comma >> user.wFortune >> comma
                >> user.wAppearance >> comma >> user.wCharacter;
            user.id = -1;
            cout << line << "號主角的信息爲:" << endl;
            cout << user << endl;
            if (1 == user.sex) //主角是男性
            {
                male[0] = user;
                matching();
                cout << "與主角匹配的屬性值爲:" << female[male[0].matchID+1] << endl;
            }
            else//主角是女性
            {
                female[0] = user;
                matching();
                cout << "與主角匹配的屬性值爲:" << male[female[0].matchID+1] << endl;
            }
            result();
            cout << "是否結束?(是Y/y)或(否N/n):";
            cin >> E;
        }
        ifs.close();        
    }
    else if ('C' == ch || 'c' == ch) //計算
    {
        while (E != 'Y' && E != 'y')
        {
            cout << "請輸入主角的屬性值:";
            cin >> user.sex >> comma >> user.fortune >> comma >> user.appearance
                >> comma >> user.character >> comma >> user.wFortune >> comma
                >> user.wAppearance >> comma >> user.wCharacter;
            user.id = 0;
            generateData(user);//生成數據
            matching();
            if (1 == user.sex) //主角是男性
                cout << "與主角匹配的屬性值爲:" << female[male[user.id+1].matchID+1] << endl;
            if (0 == user.sex) //主角是男性
                cout << "與主角匹配的屬性值爲:" << male[female[user.id+1].matchID+1] << endl;
            result();
            cout << "是否結束:是Y/y或否N/n:";
            cin >> E;
        }
    }
    else
        cout << "error!" << endl;
}

int main()
{
    srand((int)time(0));
    startProg();
    return 0;
}
View Code
相關文章
相關標籤/搜索