标签:
题三. 单词接龙 (27分)
问题描述
单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如 beast和astonish,如果接成一条龙则变为beastonish,另外相邻的两部分不能存在包含关系,例如at 和 atide 间不能相连。
输 入
输入的第一行为一个单独的整数n (n<=20)表示单词数,以下n 行每行有一个单词,输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在.
输 出
只需输出以此字母开头的最长的“龙”的长度
样 例 :
输入
5
at
touch
cheat
choose
tact
a
输出
23 (连成的“龙”为atoucheatactactouchoose)
【思路】
回溯法。
可以离线求出j接在i之后的重叠部分c[i][j],这样就可以把序列的尾巴u以及序列的长度len作为状态搜索,否则还要以string为状态搜索。
【代码】
1 #include<iostream> 2 #include<cstring> 3 using namespace std; 4 5 const int maxn = 20+5; 6 int n; 7 int c[maxn][maxn]; 8 int x[maxn],A[maxn]; //标记//序列 9 string words[maxn]; 10 int wordslen[maxn]; 11 int ans=0; 12 13 //计算a前b后的重叠长度 14 //substr截取字符串 15 int calc(string a,string b) { 16 int lena=a.size(),lenb=b.size(); 17 int len=min(lena,lenb); 18 for(int l=1;l<=len-1;l++) { //len-1不能包含 //且重叠部分尽量小 从小到大枚举 19 if(a.substr(lena-l,l)==b.substr(0,l)) 20 return l; 21 } 22 return 0; 23 } 24 25 void dfs(int u,int len) { 26 ans=max(ans,len); 27 for(int v=0;v<n;v++) if(x[v]<2 && c[u][v]) { 28 x[v]++; 29 dfs(v,len+wordslen[v]-c[u][v]); 30 x[v]--; 31 } 32 } 33 int main() { 34 ios::sync_with_stdio(false); 35 cin>>n; 36 for(int i=0;i<n;i++){ 37 cin>>words[i]; wordslen[i]=words[i].size(); 38 } 39 for(int i=0;i<n;i++) for(int j=0;j<n;j++) //自己可能与自己重叠 40 c[i][j]=calc(words[i],words[j]); 41 char ch; cin>>ch; 42 for(int i=0;i<n;i++) if(words[i][0]==ch) { 43 x[i]++; dfs(i,wordslen[i]); x[i]--; 44 } 45 cout<<ans; 46 return 0; 47 }
标签:
原文地址:http://www.cnblogs.com/lidaxin/p/4859572.html