codevs 1018 单词接龙

来源:互联网 发布:东离剑游纪 知乎 编辑:程序博客网 时间:2024/04/27 16:47

题目描述 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)

思路
n<=20 dfs
在检查重合部分长度时,即cklen从1枚举到要min(拼接的单词的长度,上次拼接的单词长度),且不包含min(因为不能单词包含单词)
因为对于 abtt 和 ttab两串,重合部分既可以看做t 也可以看做tt,因为长度要尽量长,所以我们选择返回cklen=1而非cklen=2;

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;bool can;char dc[25][25],vis[25];int ans,n;int check(int be,int no){//before   now    can=0;    int lb=strlen(dc[be]),ln=strlen(dc[no]);    for(int cklen=1;cklen<min(lb,ln);cklen++){        can=1;        for(int i=0,j=lb-cklen;i<ln,j<lb;i++,j++){            if(dc[be][j]!=dc[no][i]) can=0;        }        if(can) return cklen;    }    if(!can)    return 0;}void dfs(int last,int tot){    ans=max(ans,tot);    if(!last){        for(int i=1;i<=n;i++){            if(dc[i][0]==dc[0][0]){                vis[i]++;                dfs(i,strlen(dc[i]));                vis[i]--;            }        }    }    else     for(int i=1;i<=n;i++){        if(vis[i]<2&&check(last,i)){            vis[i]++;            dfs(i,tot+strlen(dc[i])-check(last,i));            vis[i]--;        }    }    return ;}int main(){    scanf("%d",&n);    for(int i=1;i<=n;i++){        scanf("%s",dc[i]);    }    scanf("%s",dc[0]);    dfs(0,1);    printf("%d",ans);    return 0;}
0 0
原创粉丝点击