P1019 单词接龙

题目链接
题目描述

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

输入输出格式

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

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

输入输出样例

输入样例#1:

5
at
touch
cheat
choose
tact
a

输出样例#1:

23

说明

(连成的“龙”为atoucheatactactouchoose)

NOIp2000提高组第三题

//代码有注释,下方提供纯代码(无注释)
#include
using namespace std;
string s[25];
int n,ans,add[25][25],visited[25];//add[][]数组记录的是两个可以连接的字符串合并之后重合部分的长度
//预处理的目的是统计哪些字符可以相连,若可以相连的话,连接之后重合的长度保存在add[][]数组中
void deal(int indx1,int indx2){//用s[indx1]去匹配s[indx2]!!
    int len1,len2,len,k,flag;
    len1 = s[indx1].size();
    len2 = s[indx2].size();
    len = min(len1,len2);
    for(int i = 1;i <= len;i++){//枚举所有重合的可能长度,从i开始,直到len
        flag = 0;//初始化flag变量为0
        k = i;
        for(int j = 0;j < i;j++)
		    //若两者不相等,就说明可以继续枚举寻找相等的,把flag变量置为1
            if(s[indx1][len1 - i + j] != s[indx2][j]){
                flag = 1;
                break;
            }
        //asss ssb 连接起来是assssb 长度为6,而不是!!assb!!
        if(!flag)//如果已经枚举到一个符合条件的最大重合长度(即最小的k),则退出循环,不用继续向下寻找
            break;
    }
    //flag == 1,记录最大重合长度,用len2 - k,(不是len1 - k) && 枚举的最大长度小于len,说明不存在包含关系
    if(!flag && k < len)
        add[indx1][indx2] = len2 - k;
    return;
}
void dfs(int index,int mx){
    ans = max(ans,mx);
    for(int i = 0;i < n;i++){
        if(visited[i] == 2 || !add[index][i])
            continue;
        visited[i]++;
        dfs(i,mx + add[index][i]);
        visited[i]--;
    }
    return;
}
int main(){
    scanf("%d",&n);
    for(int i = 0;i <= n;i++)
        cin >> s[i];
    for(int i = 0;i < n;i++)
        for(int j = 0;j < n;j++)
            deal(i,j);//预处理每一个单词
    for(int i = 0;i < n;i++)//每一个首字母相同的都要试一试
        if(s[n][0] == s[i][0]){
            visited[i]++;
            dfs(i,s[i].size());
            visited[i]--;
        }
    printf("%d\n",ans);
    return 0;
}


//无注释代码
#include
using namespace std;
string s[25];
int n,ans,add[25][25],visited[25];
void deal(int indx1,int indx2){
    int len1,len2,len,k,flag;
    len1 = s[indx1].size();
    len2 = s[indx2].size();
    len = min(len1,len2);
    for(int i = 1;i <= len;i++){
        flag = 0;
        k = i;
        for(int j = 0;j < i;j++)
            if(s[indx1][len1 - i + j] != s[indx2][j]){
                flag = 1;
                break;
            }
        if(!flag)
            break;
    }
    if(!flag && k < len)
        add[indx1][indx2] = len2 - k;
    return;
}
void dfs(int index,int mx){
    ans = max(ans,mx);
    for(int i = 0;i < n;i++){
        if(visited[i] == 2 || !add[index][i])
            continue;
        visited[i]++;
        dfs(i,mx + add[index][i]);
        visited[i]--;
    }
    return;
}
int main(){
    scanf("%d",&n);
    for(int i = 0;i <= n;i++)
        cin >> s[i];
    for(int i = 0;i < n;i++)
        for(int j = 0;j < n;j++)
            deal(i,j);
    for(int i = 0;i < n;i++)
        if(s[n][0] == s[i][0]){
            visited[i]++;
            dfs(i,s[i].size());
            visited[i]--;
        }
    printf("%d\n",ans);
    return 0;
}



你可能感兴趣的:(深度优先搜索)