呃…变形课上Harry碰到了一点小麻烦,因为他并不像Hermione那样能够记住所有的咒语而随意的将一个棒球变成刺猬什么的,但是他发现了变形咒语的一个统一规律:如果咒语是以a开头b结尾的一个单词,那么它的作用就恰好是使A物体变成B物体.
Harry已经将他所会的所有咒语都列成了一个表,他想让你帮忙计算一下他是否能完成老师的作业,将一个B(ball)变成一个M(Mouse),你知道,如果他自己不能完成的话,他就只好向Hermione请教,并且被迫听一大堆好好学习的道理.
测试数据有多组。每组有多行,每行一个单词,仅包括小写字母,是Harry所会的所有咒语.数字0表示一组输入结束.
如果Harry可以完成他的作业,就输出"Yes.",否则就输出"No."(不要忽略了句号)
so soon river goes them got moon begin big 0
Yes.
这道题目用DFS的思想做其实很好理解。
首先,既然每个单词只有首尾两个字符有用,我们只需要用字符数组存下两个字母就可以了。
string s;
char begi[1005],en[1005];//一些判题机上可能不可以用begin和end
while(cin>>s)
{
n++;
begi[n]=s[0];
en[n]=s[s.length()-1];
}
接下来看题目,题目中说需要一些单词首尾相连形成由’b’到’m’的序列。打个生动形象 的比方,就是英文版的成语接龙。拿样例来说:big -> got -> them就可以了,那么我们只需要判断从首字母为’b’的单词找起能不能找到尾字母为’m’的单词就行了,所以可以打出一个原始版的DFS。
bool f;//f表示有没有找到
int n;//这...就是有几个单词
char begi[1005],en[1005];
void DFS(int k)
{
if(f==1)
return ;//找到了就不用找了
if(en[k]=='m')
{
f=1;
return ;
}
for(int i=1;i<=n;i++)
{
if(begi[i]==en[k])
DFS(i);//反复寻找
}
}
现在我们看这个原始的DFS能不能进行一些改进。我们会发现,用这个程序来找能不能找到是完全可以的,但是如果找不到的话,它就会一直进行反复横跳。比如输入"ba ab" ,程序就会ba -> ab -> ba -> ab…进入无限死循环。所以我们需要增加一个bool的vis数组来判断这个单词是否使用过(因为没有必要再用第二次)。如果使用过了就变成1,没有即为0。还有不要忘记找不到的话要重新把它变成0。
int n;
bool f,vis[1005];//标记是否用过
char begi[1005],en[1005];
void DFS(int k)
{
if(f==1)
return ;
if(en[k]=='m')
{
f=1;
return ;
}
for(int i=1;i<=n;i++)
{
if(vis[i]==0&&begi[i]==en[k])//还没用过
{
vis[i]=1;//现在用过了
DFS(i);
vis[i]=0;//用过了还是找不到,所以不要用
}
}
}
最后一个就是输入输出问题,一般来说这是最简单的问题,但是这道题目的输入输出还是很棘手的。一开始我企图用一个while(1)解决问题,但是谁知道while(cin)的功能太过强大导致^z都被当做字符读入了……所以还是想办法吧。显而易见,0表示一段单词,那么我们只需要将两个0中间的一段单词进行处理就可以了,同时,处理还可以在读入0的时候直接处理掉,非(hen)常(bu)方便。
int n;
bool f,vis[1005];
char begi[1005],en[1005];
string s;
while(cin>>s)
{
if(s[0]=='0')//发现是0就处理一下
{
for(int i=1;i<=n;i++)
vis[i]=0;//别忘了初始化 ps:memset的速度慢,不建议使用
for(int i=1;i<=n;i++)
{
if(begi[i]=='b')//开头是b的就DFS一下
{
vis[i]=1;
DFS(i);
}
}
if(f==1)//找到了
cout<<"Yes."<<endl;
else//没找到
cout<<"No."<<endl;
n=0;f=0;//初始化*2
}
else//如果是单词就存进去
{
n++;
begi[n]=s[0];
en[n]=s[s.length()-1];
}
}
好了,以上就是这道题目的做法详解。废话不多说了,上完整代码——
#include
//#include
using namespace std;
int n;
bool f,vis[1005];
char begi[1005],en[1005];
string s;
void DFS(int k)
{
if(f==1)
return ;
if(en[k]=='m')
{
f=1;
return ;
}
for(int i=1;i<=n;i++)
{
if(vis[i]==0&&begi[i]==en[k])
{
vis[i]=1;
DFS(i);
vis[i]=0;
}
}
}
int main()
{
while(cin>>s)
{
if(s[0]=='0')
{
for(int i=1;i<=n;i++)
vis[i]=0;
for(int i=1;i<=n;i++)
{
if(begi[i]=='b')
{
vis[i]=1;
DFS(i);
}
}
if(f==1)
cout<<"Yes."<<endl;
else
cout<<"No."<<endl;
n=0;f=0;
}
else
{
n++;
begi[n]=s[0];
en[n]=s[s.length()-1];
}
}
return 0;
}
另外,这里还附上BFS的代码,至于我为什么不写题解么……因为懒得不会 讲。
ps:这题其实BFS比DFS快很多,不过……DFS打起来方便嘛。
#include
#include
#include
#include
using namespace std;
int n;
struct node
{
char from;
char to;
int visit;
}str[10000];
int main()
{
int i=1;
string s1;
while(cin>>s1)
{
str[0].from=s1[0];
str[0].to=s1[s1.size()-1];
str[0].visit=0;
while(i++)
{
cin>>s1;
if(s1[0]=='0')
break;
str[i].from=s1[0];
str[i].to=s1[s1.size()-1];
str[i].visit=0;
}
int n=i;
int f=0;
queue<char>s;
s.push('b');
while(!s.empty())
{
char temp=s.front();
s.pop();
for(i=0;i<n;i++)
{
if(str[i].from==temp)
{
if(str[i].to=='m')
{
cout<<"Yes."<<endl;
f=1;
break;
}
if(str[i].visit==0)
{
s.push(str[i].to);
str[i].visit=1;
}
}
}
if(f)
break;
}
if(!f)
cout<<"No."<<endl;
i=1;
}
return 0;
}