1. 程式人生 > >洛谷P1019 單詞接龍(DFS)

洛谷P1019 單詞接龍(DFS)

題目描述

單詞接龍是一個與我們經常玩的成語接龍相類似的遊戲,現在我們已知一組單詞,且給定一個開頭的字母,要求出以這個字母開頭的最長的“龍”(每個單詞都最多在“龍”中出現兩次),在兩個單詞相連時,其重合部分合為一部分,例如 beast和astonish,如果接成一條龍則變為beastonish,另外相鄰的兩部分不能存在包含關係,例如at 和 atide 間不能相連。

輸入輸出格式

輸入格式:

輸入的第一行為一個單獨的整數n (n≤20)表示單詞數,以下n 行每行有一個單詞,輸入的最後一行為一個單個字元,表示“龍”開頭的字母。你可以假定以此字母開頭的“龍”一定存在.

輸出格式:

只需輸出以此字母開頭的最長的“龍”的長度

輸入輸出樣例

輸入樣例#1: 

5
at
touch
cheat
choose
tact
a

輸出樣例#1: 

23

思路:挺簡單的一道搜尋題,比賽的時候最後看的這個題,大致想了一下思路明確了用搜索搞,沒仔細考慮怎麼處理單詞連線部分,,,就翻車了。賽後A...心累。開學後什麼狀態都沒了....整天東忙西忙的,唉。

程式碼如下:

#include<iostream>
#include<cstring>
#define per(i,a,b) for(int i=a;i<=b;++i)
#define rep(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
int n,p[22],vis[22],l,ans,mp[21][21]; 
string s[21];
int fun(string a,string b)
{
    int w=min(a.length(),b.length());
    per(i,1,w)
      if(a.substr(a.length()-i,i)==b.substr(0,i))//判斷後半段與前半段是否相等 
      return b.length()-i;//返回去重後的長度 
    return 0;
}
void dfs(int a,int c)//a為當前第幾節軀幹,c為長度 
{
    per(i,1,n)
    {
        if(mp[p[a]][i]!=0&&vis[i]<2)//可連線且使用次數小於2 
        {
            p[a+1]=i;//指向上一節 
            l+=mp[p[a]][i];//加長度 
            vis[i]++;
            ans=max(l,ans);
            dfs(a+1,l);
            l-=mp[p[a]][i];
            vis[i]--;
        }
    }
}
int main()
{
    cin>>n;
    char a;
    per(i,1,n) cin>>s[i];
    cin>>a;
    per(i,1,n)//預處理 
    {  
	    if(s[i][0]==a) 
		mp[0][i]=s[i].length();//可以接龍頭的長度 
    }
    per(i,1,n)
    {
        per(j,1,n)
        { 
            mp[i][j]=fun(s[i],s[j]);//判斷是否可連線,返回去重後的長度 
            //cout<<mp[i][j]<<"*";
        } //cout<<endl;
    } 
    dfs(0,0);
    cout<<ans;
    return 0; 
}