第五题: 找出直系亲属。如果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;
}