1. 程式人生 > >【洛谷】 P1019 單詞接龍-(預處理+dfs)

【洛谷】 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提高組第三題

思路:這個題目要求出的是最長的接起來的字串的長度,那就必須要求出每一個他給出的單詞的重合數,也就是說我要用到任意兩個單詞的時候,你要先知道這兩個單詞是什麼情況,

有三類的單詞是不能用的:

1.兩個單詞之間沒有重合部分的,既不能連結的

2.用的次數超過兩次的,這個題目不是用過一次,注意看題吧。。。。

3.相互包含的,這個可以根據他重合字元的長度來判斷。

其實也就是多了一個函式預處理所有的單詞,知道單詞之間的關係後,深度搜索的想法自然就出了。。

程式碼:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<string>
using namespace std;

int n;
string tr[30];
int yc[30][30];
int vis[30];

int mp(int x,int y) //預處理兩個單詞之間的重合字元的數目
{
    bool pp=true;
    int ky=0;
    for(int k=tr[x].size()-1; k>=0; k--)
    {
        for(int kx=k; kx<tr[x].size(); kx++)
        {
            if(tr[x][kx]!=tr[y][ky++])
            {
                pp=false;
                break;
            }
        }

        if(pp==true)
        {
            return tr[x].size()-k;
        }
        ky=0;
        pp=true;
    }
    return 0;
}

char ch;
int ans=-1,an=0; //an儲存某種或許可行單詞連線方式的長度
                        //ans儲存總體的最大值。

void dfs(int p)
{
    bool jx=false;
    for(int j=1; j<=n; j++)
    {
        if(vis[j]>=2)
            continue;
        if(yc[p][j]==0)
            continue;

        if(yc[p][j]==tr[p].size()||yc[p][j]==tr[j].size())
            continue;  //三種不可行的狀態


        an+=tr[j].size()-yc[p][j];
        vis[j]++;
        jx=true;
        dfs(j);        //注意回溯
        an-=tr[j].size()-yc[p][j];
        vis[j]--;
    }

    if(jx==false)  //連線方式找完判斷一下大小;
    {
        ans=max(ans,an);
    }

    return ;
}

int main()
{
    scanf("%d",&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]=mp(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;
        }
    printf("%d\n",ans);
    return 0;
}