7-27 家谱处理 (30 分)(详解+map做法)map真香啊
一:題目
人類學研究對于家族很感興趣,于是研究人員搜集了一些家族的家譜進行研究。實驗中,使用計算機處理家譜。為了實現這個目的,研究人員將家譜轉換為文本文件。下面為家譜文本文件的實例:
John
Robert
Frank
Andrew
Nancy
David
家譜文本文件中,每一行包含一個人的名字。第一行中的名字是這個家族最早的祖先。家譜僅包含最早祖先的后代,而他們的丈夫或妻子不出現在家譜中。每個人的子女比父母多縮進2個空格。以上述家譜文本文件為例,John這個家族最早的祖先,他有兩個子女Robert和Nancy,Robert有兩個子女Frank和Andrew,Nancy只有一個子女David。
在實驗中,研究人員還收集了家庭文件,并提取了家譜中有關兩個人關系的陳述語句。下面為家譜中關系的陳述語句實例:
John is the parent of Robert
Robert is a sibling of Nancy
David is a descendant of Robert
研究人員需要判斷每個陳述語句是真還是假,請編寫程序幫助研究人員判斷。
輸入格式:
輸入首先給出2個正整數N(2≤N≤100)和M(≤100),其中N為家譜中名字的數量,M為家譜中陳述語句的數量,輸入的每行不超過70個字符。
名字的字符串由不超過10個英文字母組成。在家譜中的第一行給出的名字前沒有縮進空格。家譜中的其他名字至少縮進2個空格,即他們是家譜中最早祖先(第一行給出的名字)的后代,且如果家譜中一個名字前縮進k個空格,則下一行中名字至多縮進k+2個空格。
在一個家譜中同樣的名字不會出現兩次,且家譜中沒有出現的名字不會出現在陳述語句中。每句陳述語句格式如下,其中X和Y為家譜中的不同名字:
X is a child of Y
X is the parent of Y
X is a sibling of Y
X is a descendant of Y
X is an ancestor of Y
輸出格式:
對于測試用例中的每句陳述語句,在一行中輸出True,如果陳述為真,或False,如果陳述為假。
輸入樣例:
6 5
John
Robert
Frank
Andrew
Nancy
David
Robert is a child of John
Robert is an ancestor of Andrew
Robert is a sibling of Nancy
Nancy is the parent of Frank
John is a descendant of Andrew
輸出樣例:
True
True
True
False
False
二:思路
用map容器記錄空格,再用一個map來記錄關系 ,
思路分析:
第一步:
x是y的孩子---------> y比x多兩個空格
x是y的父母---------> x比y少兩個空格
x是y的兄弟姐妹-----> 空格數相等
x是y的后代---------> 只要x的空格數比y 多就可以
x是y的祖先---------> y比x多的空格數 大于等于2
第二步:
考慮 關系 代碼當中有解釋 很炫的
三:上碼
//思路分析: //第一步: //x是y的孩子---------> y比x多兩個空格 //x是y的父母---------> x比y少兩個空格 //x是y的兄弟姐妹-----> 空格數相等 //x是y的后代---------> 只要x的空格數比y 多就可以 //x是y的祖先---------> y比x多的空格數 大于等于2 //第二步: //考慮 關系 // //X is a child of Y //X is the parent of Y //X is a sibling of Y //X is a descendant of Y //X is an ancestor of Y#include<bits/stdc++.h> using namespace std;map<string,string>father;//存關系 father[孩子] = 雙親 int spaceNum(string str,int cnt){ //計算空格數 for( int i = 0; i < str.size(); i++ ){if(str[i] == ' ')cnt++;}return cnt; }int judgment(string str1,string str2){ //往上找爹 用于解決測試點三 while( father[str1] != str2 ){if(father[str1] == "zuxian")break;string temp;temp = father[str1]; str1 = temp;}if(father[str1] == str2 )return 1;elsereturn 0; }int main() {map<string,int>m; map<string,int>:: iterator t;vector<string>v(110);//存名字 int N,M;cin >> N >> M;getchar();//出去換行符的干擾 for( int i = 0; i < N; i++ ){string str;getline(cin,str);int count = spaceNum(str,0);if( count == 0 ){father[str] = "zuxian";v[0] = str; //如果不給容器的大小 即vector<string>v(N); 則需要用v.push_back(); // v.push_back(str); }else{string str1 = str.substr(count);//這里為截取字符串 將空格去掉 m[str1] = count;//這里count 可能會重復 但沒關系,map當中不存在鍵值重復,存在關鍵值重復father[str1] = v[count/2 -1]; //這里非常巧妙,學大佬的 因為孩子的空個數總是比雙親少兩個 count/2-1這樣 就 可 以 將 雙親和孩子yiyi對應上 v[count/2] = str1; //當空格數相等時,會發生覆蓋 } } for( int i = 0; i < M; i++ ){string a,b,c,d,e,f;cin >> a >> b >> c >> d >> e >> f;if( d == "child" ){if(m[a] - m[f] == 2 && father[a] == f)// father[a] = f a的雙親是f cout << "True" << endl;elsecout << "False" << endl;}if( d == "parent" ){if(m[f] - m[a] == 2 && father[f] == a)cout << "True" << endl;elsecout << "False" << endl; } if( d == "sibling" ){if(m[a] - m[f] == 0 && father[a] == father[f])cout << "True" << endl;elsecout << "False" << endl; } if( d == "descendant" ){int a1 = judgment(a,f); if( (m[a] - m[f] > 2 && a1 == 1) || father[f] == "zuxian" ) //如果這里的f是祖先的話 任何他的孩子 都是后代 cout << "True" << endl;elsecout << "False" << endl; }if( d == "ancestor" ) {int a1 = judgment(f,a); if((m[f] - m[a] >= 2 && a1 == 1) || father[a] == "zuxian" )cout << "True" << endl;elsecout << "False" << endl; }}}//6 1 //John // Robert // Frank // Andrew // Nancy // David //John is a descendant of Andrew四:總結
肝了5個小時 覺得值得 加油陌生人!
總結
以上是生活随笔為你收集整理的7-27 家谱处理 (30 分)(详解+map做法)map真香啊的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎么疏通经络
- 下一篇: 7-28 搜索树判断 (25 分)(思路