Loading

洛谷 p1019 单词接龙

题目描述

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

输入输出格式

输入格式:

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

输出格式:

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

 

分析

本题还是一道dfs问题 重要的是如何处理给出的单词 以及如何构建一个dfs

首先我们注意到,想要找到最长的“龙”,根据贪心的原则,重合部分要取最小 比如 asdd 和ddas 这两个“单词”,合起来就是adddas 也就是只重合一个字母 而不是asddas 这一点是需要注意的

首先为了dfs的方便 我们可以构造一个数组 p[i][j] 代表 i 单词在前 j 单词在后的时候会重合多少字母 还是asdd和ddas的例子 如果i 单词是asdd,j 单词是ddas 那么p[i][j]=1,p[j][i]=2

至于构造的方式 看下面的代码就好了 注意一定是最小的重合部分。

 

代码:

#include<bits/stdc++.h>

using namespace std;

string s[30];
char d;
int n,vis[21],p[30][30],ans=-1,an=0;

void ff(int x,int y)
{
    int k,kx;
    int ky=0;
    int flag=1;
    for(k=s[x].size()-1;k>=0;k--)
    {
    for(kx=k;kx<=s[x].size()-1;kx++)
    {
        if(s[x][kx]!=s[y][ky++]) 
        {
            flag=0;
            break;
        }
    }
    if(flag) //只要有重合部分就跳出,这样保证了重合的是最小的
    {
        p[x][y]=s[x].size()-k;
        return;
    }
    ky=0;
    flag=1;
    }
    return ;
}


void dfs(int x)
{
    int i,flag=0;
    for(i=0;i<n;i++)
    if(vis[i]<2&&p[x][i]!=0&&s[x].size()!=p[x][i]&&s[i].size()!=p[x][i])
    {
        flag=1;
        an+=s[i].size()-p[x][i];
        vis[i]++;
        dfs(i);
        vis[i]--;
        an-=s[i].size()-p[x][i];
    }
    if(!flag)  //如果没有新的单词可以“接龙”,判断是否是更长的“龙”并返回
    ans=max(ans,an);
    return;
}

int main()
{
    int i,j;
    cin>>n;
    for(i=0;i<n;i++)
    {
        cin>>s[i];
    }
    for(i=0;i<n;i++)
    for(j=0;j<n;j++)
    {
        ff(i,j);
    }
    cin>>d;
    for(i=0;i<n;i++)
    {
        if(s[i][0]==d)
        {
            vis[i]++;
            an=s[i].size();    //不要忘了这一句 而且是 = 不是+=!!
            dfs(i);
            vis[i]=0;
        }
    }
    cout<<ans;
 } 

 

posted @ 2019-03-28 09:07  WinterFa1L  阅读(291)  评论(0编辑  收藏  举报