NOIP2000提高組 單詞接龍
題目描述
單詞接龍是一個與我們經常玩的成語接龍相類似的遊戲,現在我們已知一組單詞,且給定一個開頭的字母,要求出以這個字母開頭的最長的“龍”(每個單詞都最多在“龍”中出現兩次),在兩個單詞相連時,其重合部分合爲一部分,例如 beast和astonish,如果接成一條龍則變爲beastonish,另外相鄰的兩部分不能存在包含關係,例如at 和 atide 間不能相連。輸入輸出格式
輸入格式:
輸入的第一行爲一個單獨的整數n (n<=20)表示單詞數,以下n 行每行有一個單詞,輸入的最後一行爲一個單個字符,表示“龍”開頭的字母。你可以假定以此字母開頭的“龍”一定存在.輸出格式:
只需輸出以此字母開頭的最長的“龍”的長度輸入輸出樣例
輸入樣例:
5at
touch
cheat
choose
tact
a
輸出輸出樣例
23輸出樣例說明:連成的“龍”爲atoucheatactactouchoose
解題分析
由於單詞個數不超過20,因此可以通過回溯法嘗試所有情況。在進行回溯法之前先做預處理,即確定每兩個單詞之間是否能連接,如果能連接,則記錄交叉的長度。該長度也被用於在進行兩個單詞連接時計算總長度。
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define N 22
string words[N];
int n, relation[N][N], used[N] = {0}, ans[2*N], ans1[2*N], result = 0, de;
// 計算兩個單詞之間的交叉情況,x在前,y在後,返回交叉長度
int re(int x, int y){
string str1 = words[x], str2 = words[y];
int i, j, k, len1 = str1.size(), len2 = str2.size();
for(k=1; k<=min(len1, len2); k++){
for(i=0; i result){
result = len;
de = depth;
for(i=0; i<=depth; i++){ // 記錄字符串如何連接,可以忽略
ans[i] = ans1[i];
}
}
for(i=1; i<=n; i++){
if(relation[k][i]>0 && used[i]<2){
len += words[i].size() - relation[k][i]; // 當前長度
used[i]++;
ans1[depth] = i;
dfs(i, depth+1, len);
len -= words[i].size() - relation[k][i];
used[i]--;
}
}
}
int main(){
ios::sync_with_stdio(false);
int i, j;
cin>>n;
for(i=1; i<=n; i++)
cin>>words[i];
cin>>words[0];
init();
ans1[0] = 0;
dfs(0, 1, 1);
cout<