POJ 2023 Choose Your Own Adventure(树形,dfs,简单题)
题意:
输入一个整数n,表示有n组测试数据,
每组第一行输入一个整数x表示该组测试一共有x页,接下来输入x行,每行表示一页,
每页或者以C开头(第一页都是以C开头),或者以E开头,中间用引号括起一段文字。
以C开头的末尾输入两个数字a,b表示该页完后可以跳转到第a页或第b页,
以E开头的末尾输入一个单词,或者是HAPPY或者是GRISLY(有且仅有一页以HAPPY结尾)。
现在要求你根据输入找出以第一页开头,以HAPPY结尾的路径,输出路径上每一页中间引号里面的内容,不包含引号。
思路:建立树,用dfs深搜。
要注意的是数据中可能会有死循环出现,会导致RE。。。
另外:本题读取句子可采用的方法:
cin.getline(page[j],258,'\"')
参考网址
http://hi.baidu.com/kskr/blog/item/cb00cc3deadf45c49f3d6279.html
#include <iostream> #include <stdio.h> #include <map> #include <string.h> #include <algorithm> const int maxn=110; using namespace std; int t,n; int endnum; //以HAPPY结尾的页数 int pri[maxn]; //前驱 bool ok; //标记是否已经找到路径 int vis[maxn]; //标记该页数是否被访问过 struct Page{ int mark; char sentence[300]; int len; int son[2]; //跳转的页码 char ending[10]; bool flag; //flag为true表示该页是HAPPY }page[maxn]; void dfs(int u){ if(ok) return; vis[u]=1; //没用vis标记前,RE;后来网上查了,有人说数据中有循环,便加上了标记,结果WA,忘记输出STORY X了。。。 if(page[u].mark){ for(int i=0;i<2;i++){ int v=page[u].son[i]; if(!vis[v]){ pri[v]=u; dfs(v); } } } else{ if(page[u].flag){ ok=true; endnum=u; } } } int main() { char s[3]; char c; int len; cin>>t; for(int q=1;q<=t;q++){ cout<<"STORY "<<q<<endl; memset(pri,-1,sizeof(pri)); memset(vis,0,sizeof(vis)); cin>>n; for(int i=1;i<=n;i++){ scanf("%s",s); page[i].mark=0; if(s[0]=='C'){ page[i].mark=1; c=getchar(); while(c!='"') c=getchar(); len=0; //读取双引号里的句子 while((c=getchar())!='"') page[i].sentence[len++]=c; page[i].len=len; scanf("%d%d",&page[i].son[0],&page[i].son[1]); } else{ c=getchar(); while(c!='"') c=getchar(); len=0; //读取双引号里的句子 while((c=getchar())!='"') page[i].sentence[len++]=c; page[i].len=len; scanf("%s",page[i].ending); if(strcmp(page[i].ending,"HAPPY")==0){ page[i].flag=true; } else{ page[i].flag=false; } } } pri[1]=1; ok=false; dfs(1); int idx=0; int res[maxn]; res[idx++]=endnum; //存储路径 while(pri[endnum]!=endnum){ res[idx++]=pri[endnum]; endnum=pri[endnum]; } for(int i=idx-1;i>=0;i--){ for(int j=0;j<page[res[i]].len;j++){ cout<<page[res[i]].sentence[j]; } cout<<endl; } } return 0; }