NOIP2000第三题——单词接龙正解
本题不是太难,虽然放在提高组里,但水平还是普及的。
重点是如何判断两个单词能连接接在一起。
首先注意题目中的几点:
1.单词最多只能用两遍
2.单词可以不全部用完
3.单词不能被完全包含
4.建议不要每做一次判断一下字符串的长度,用一个数组专门存储长度(如代码中的Size数组),这样会省一些时间。
个人认为代码中的Depth_First_Search函数中的第二层循环(防止两个单词互相包含)和Judge函数比较难懂,用样例手模几遍应该就能理解。
#include <bits/stdc++.h>
using namespace std;
string INnumber[21];//输入数组
short NMnumber[21];//判断使用的次数
long ACanswer;//正解
long Size[21];//测量每个单词的长度
int N;
bool Judge(int num,int first,int second)//这个函数的作用是判断两个单词是否能连接
{
for(int i=num,j=0;i>0,j<num;i--,j++)
{
if(INnumber[first][Size[first]-i]!=INnumber[second][j])
{
return false;
}//如果任意一个字符不符合,就退出
}
return true;
}
void Depth_First_Search(long Max,int num)//深搜
{
ACanswer=max(ACanswer,Max);//更新
for(int i=0;i<N;i++)//将所有单词扫一遍
{
if(NMnumber[i]>0)//如果可以取
{
for(int j=1;j<=(min(Size[num],Size[i])-1);j++)//防止两个单词互相包含
{
if(INnumber[i][0]==INnumber[num][Size[num]-j])//如果有一个字母相同
{
if(Judge(j,num,i)==true)//判断是否可以连接
{
NMnumber[i]--;
Depth_First_Search(Max-j+Size[i],i);//增加总长度
NMnumber[i]++;
}//回溯
}
}
}
}
return;
}
int main(void)
{
cin>>N;
for(int i=0;i<N;i++)
{
cin>>INnumber[i];
Size[i]=INnumber[i].size();
NMnumber[i]=2;
}
char Start;
cin>>Start;
//入口
for(int i=0;i<N;i++)
{
if(INnumber[i][0]==Start)//寻找入口
{
NMnumber[i]--;
Depth_First_Search(Size[i],i);
NMnumber[i]++;
}
}
cout<<ACanswer<<endl;
//输出正解
return 0;
}