洛谷P1019:单词接龙(DFS)

题目描述

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

输入输出格式

输入格式:
输入的第一行为一个单独的整数nn (n \le 20n≤20)表示单词数,以下nn 行每行有一个单词,输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在.

输出格式:
只需输出以此字母开头的最长的“龙”的长度

输入输出样例

输入样例#1:
5
at
touch
cheat
choose
tact
a
输出样例#1:
23

说明
(连成的“龙”为atoucheatactactouchoose)

NOIp2000提高组第三题

AC代码

#include <bits/stdc++.h>
using namespace std;
char ch[25][1000];
int vis[25];
int ml,n;
// 检查从第i个字符串第j个字符开始的字符串L与第k个字符串前L个字符组成的字符串是否相同
bool check(int i,int j,int k)
{
    int l=strlen(ch[i])-j;
    for(int u=0;u<l;u++)
        if(ch[k][u]!=ch[i][j+u]||u>=strlen(ch[k])-1)
            return false;
    return true;
}
// 搜索从第i个单词的第j个字符开始的字符串
void dfs(int i,int j,int l)
{
//    更新ml的值
    ml=max(ml,l);
    for(int k=1;k<=n;k++)
    {
//        如果第k个字符串用的次数少于2次,或者满足组成“龙”的条件
        if(vis[k]<2&&check(i,j,k))
        {
            vis[k]++;
            for(int m=1;m<strlen(ch[k]);m++)
                dfs(k,m,l+strlen(ch[k])-strlen(ch[i])+j);
//            回溯
            vis[k]--;
        }
    }
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>ch[i];
    cin>>ch[0][0];
    dfs(0,0,1);
    cout<<ml<<endl;
    return 0;
}
posted @ 2018-11-22 16:56  友人-A  阅读(227)  评论(0编辑  收藏  举报