第五題: 找出直系親屬。如果A,B是C的父母親,則A,B是C的parent,C是A,B的child,如果A,B是C的(外)祖父,祖母,則A,B是C的grandparent,C是A,B的grandchild,如果A,B是C的(外)曾祖父,曾祖母,則A,B是C的great-grandparent,C是A,B的great-grandchild,之後再多一輩,則在關係上加一個great-。
輸入:n(0<=n<=26)表示n個親屬關係,形式爲ABC,表示A的父母親分別是B,C,如果A的父母親信息不全,則用-代替,例如A-C。m(。。。)代表測試用例數,形式AB。輸出:AB的關係,如A是B的直系親屬,按上述要求輸出關係,如果A,B沒有關係,輸出-。當n爲0時結束。
Input:
3 2
ABC
CDE
EFG
FA
BE
0 0
Output:
great-grandparent
這道題目重點之一在於信息的組織,因爲任意一個節點有兩個雙親,而兒女個數不是確定的,因此沒法使用一般的樹結構來組織信息,圖結構不能反映層次關係 更加不好處理,可以採用靜態鏈表的方案 發現這種方案在這種小型算法程序中比較好用 位置指針便於使用 也避免繁瑣的指針細節 接下來就是沿着這個節點位置向祖先路徑上遍歷,訪問時檢查是否匹配,一旦查找到就立刻結束,使用tag作爲深度展開的入口檢查條件,因爲只能訪問祖先,調換順序 再訪問一次,如果還未找到不要忽略了二者可能是兄弟結點(這裏題目不是很清,要注意陷阱),最後的分支是輸出二者沒有任何關係
總結
重點在於三點
1.選擇合適的組織信息方案;
2,開始時記得把所有的結點標記爲空(-1),以便作爲遞歸終止標識//注意開始犯的錯誤,只初始到n
3,熟悉搜索框架,進行必要的剪枝
//一開始犯了一個錯誤,n只是關係的數目,而不是結點編號的最大值,所以調試的時候出現異常,因爲所有後面未能初始化的結點都被默認初始化爲0,即爲A的孩子
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
int tag,level;
int convert(char c)
{
return c-'A';
}
struct node
{
int father,mother;//直接轉換爲編號,不用字母
};
node record[30];
void search(int from,int to,int count)
{
if(record[from].mother==to||record[from].father==to)
{
level=count;
tag=0;//標記,結束探查 減枝;
return;
}
if(record[from].mother!=-1&&tag)search(record[from].mother,to,count+1);
if(record[from].father!=-1&&tag)search(record[from].father,to,count+1);
}
int main()
{
int n,m;
while(cin>>n>>m&&n)
{
int i;
for(i=0;i<26;i++)//因爲不可能窮極所有的父母信息,所以初始化爲未知是最方便的以後作爲遍歷終止條件
record[i].mother=record[i].father=-1;//沒說編號規則,這裏改成26更好一點
string input;
for(i=0;i<n;i++)
{
cin>>input;
int number;
number=convert(input[0]);
if(input[1]!='-')record[number].father=convert(input[1]);
if(input[2]!='-')record[number].mother=convert(input[2]);
}
while(m--)
{
char from,to;
cin>>from>>to;
tag=1;
search(convert(from),convert(to),0);
if(!tag)//找到,to爲from的祖先
{
if(level==0)cout<<"child"<<endl;
else if(level==1)cout<<"grandchild"<<endl;
else
{
while(level>1)cout<<"great-",level--;
cout<<"grandchild"<<endl;
}
continue;
}
tag=1;
search(convert(to),convert(from),0);
if(!tag)//找到,from爲to的祖先
{
if(level==0)cout<<"parent"<<endl;
else if(level==1)cout<<"grandparent"<<endl;
else
{
while(level>1)cout<<"great-",level--;
cout<<"grandparent"<<endl;
}
continue;
}
//注意要考慮二者是不是兄弟,這裏就不考慮單親相同了
int v1=convert(from);
int v2=convert(to);
if((record[v1].mother==record[v2].mother)&&(record[v1].father==record[v2].father))
{
cout<<"brother"<<endl;
continue;
}
cout<<"-"<<endl;//unknow relationship
}
}
return 0;
}