鹿我所录的博客

记录我在学习C#中的点点滴滴,记录下以备后来人借鉴。

 

洛谷P1019单词接龙-题解

原题:

 

 

 思路:

数据范围很小(n<=20)所以考虑搜索。

最为朴素的想法——对于每一个单词,我考虑后面能接哪些单词,并分别尝试计算答案。

但是随之而来的就是一个问题——我要如何知道后面能接哪些单词?

解决方法很简单,只要匹配一下就好了。

但是,难道我每次递归,都要匹配一下吗?这肯定是不行的,时间复杂度会爆炸。

所以我们理所当然地想到预处理。

先预处理出每两个单词的最小重叠部分(只要数即可),然后按照上面的规则递归

代码:

#include<bits/stdc++.h>
using namespace std;
int n;
string tr[30];
int yc[30][30];
int vis[30];
char ch;
int an=0;
int ans=-1;
int mt(int i,int j)
{
    bool bl=true;
    int kj=0;
    for(int k=tr[i].size()-1;k>=0;k--)
    {
        for(int ki=k;ki<tr[i].size();ki++)
            if(tr[i][ki]!=tr[j][kj++])
            {
                bl=false;
                break;
            }
        if(bl)  
        {
            return tr[i].size()-k;
        }
        kj=0;
        bl=true;
    }
    return 0;
}
void dfs(int p)
{
    bool jx=false; 
    for(int i=1;i<=n;i++)
    {
        if(vis[i]>=2)
            continue;
        if(yc[p][i]==0)
            continue;
        if(yc[p][i]==tr[i].size()||yc[p][i]==tr[p].size())
            continue;
        vis[i]++;
        an+=tr[i].size()-yc[p][i];
        jx=true;
        dfs(i);
        vis[i]--;
        an-=tr[i].size()-yc[p][i];
    }
    if(!jx)
        ans=max(ans,an);
    return;
}
int main()
{
    cin >> n;
    for(int i=1;i<=n;i++)
        cin >> tr[i];
    cin >> ch;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            yc[i][j]=mt(i,j);
    for(int i=1;i<=n;i++)
    {
        if(tr[i][0]==ch)
        {
            vis[i]++;
            an=tr[i].size();
            dfs(i);
            vis[i]=0;
        }
    }
    cout << ans << endl;
    return 0;
}

  

posted on 2020-08-06 09:17  鹿我所录  阅读(172)  评论(0编辑  收藏  举报

导航