【NOIP 2000 提高组 T3】单词接龙(dfs)

题目描述 Description
单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如beast和astonish,如果接成一条龙则变为beastonish,另外相邻的两部分不能存在包含关系,例如at和atide间不能相连。

输入描述 Input Description
输入的第一行为一个单独的整数n(n<=20)表示单词数,以下n行每行有一个单词,输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在.

输出描述 Output Description
只需输出以此字母开头的最长的“龙”的长度

样例输入 Sample Input
5
at
touch
cheat
choose
tact
a

样例输出 Sample Output
23

数据范围及提示 Data Size & Hint
(连成的“龙”为atoucheatactactouchoose)

题解:数据范围很小可以用dfs来做,我们先枚举第一个字母与指定字母相同的单词,然后进行dfs。对于两个单词能否接起来,我们写一个check函数,先枚举可能重合的长度,然后从第一个单词第一位和第二个单词最后一位开始比较,直到他们能够接起来,返回接起来时的长度。

代码如下

#include
#include
#include
using namespace std;
const int MAXN=1010;
int n,maxx=0,used[MAXN];
struct word
{
    char a[MAXN];
}s[MAXN];
int check(int l,int r)
{
    int ll=strlen(s[l].a);
    int lr=strlen(s[r].a);
    for(int k=1;k//枚举能够接起来的长度 
    {
        bool flag=0;
        for(int i=ll-k,j=0;i//第一个单词从前往后,第二个单词从后往前 
            if(s[l].a[i]!=s[r].a[j])
            {
                flag=1;
                break;
            }
        }
        if(!flag) return k;//返回能接起来的最小长度 
    }
    return 0;
}
void dfs(int last,int len)//last是当前单词的编号,len是当前接起来的龙的长度 
{
    if(!last)
    {
        for(int i=1;i<=n;i++)
            if(s[i].a[0]==s[0].a[0]&&used[i]<2)//先找首字母与给定字母相同的单词 
            {
                used[i]++;
                dfs(i,strlen(s[i].a));
                used[i]--;
            }
    }
    else
    {
        maxx=max(maxx,len);//记录一下龙的最大值 
        for(int i=1;i<=n;i++)
        {
            int x=check(last,i);//返回接起来的最小长度 
            if(x&&used[i]<2)
            {
                used[i]++;
                dfs(i,len+strlen(s[i].a)-x);//当前长度加上新单词长度减去重合部分的长度 
                used[i]--;
            }
        }
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%s",s[i].a);
    scanf("%s",s[0].a);
    dfs(0,1);
    printf("%d\n",maxx);
    return 0;
}

你可能感兴趣的:(NOIP历年真题,===搜索===,DFS)