本题在洛谷上的链接:https://www.luogu.org/problemnew/show/P1019
颓废了一段时间,,,现在打算一遍学着数论基础,一遍做着搜索之类的题目提高代码能力。
这道题数据范围小,是一道典型的搜索题,但是对解题能力还是有一定要求的。
注意是解题能力!我认为,他包括这几部分:读题懂题意,化归到算法模型上,编写代码处理好细节。
读懂题是解决题目的前提,有时解题时间长、出错率高不是因为知识掌握少,代码写得乱,就是因为最开始没读懂题就动手。
这道题的话,需要读出以下几点:
1、每个单词最多出现2次。
2、单词有重合部分,且应该是指最小重合部分。
3、存在包含关系的两个单词不能相连。
结合数据范围,我们很容易想到可以用搜索。每次记录已构成的龙最后一个单词以及龙的长度。每次搜索下一个单词,考虑能否接上。
如果不存在可以接上的单词,则用现在累计的长度更新答案;若存在,将其接上,注意累计长度是加上新单词的长度-两单词重叠部分。
代码能力需要做大量的题才能练出来,同样是实现一个功能,代码能力强就可以快速高效地实现,而且不易出错。
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<string> 5 using namespace std; 6 const int maxn=25; 7 int n,ans,ccnt[maxn][maxn],vis[maxn]; 8 char c; 9 string s[maxn]; 10 inline int con(string a,string b) { 11 int la=a.length(),lb=b.length(); 12 for(int cnt=1;cnt<=min(la,lb);++cnt) { 13 int flag=1; 14 for(int i=la-cnt,j=0;j<cnt;++i,++j) 15 if(a[i]!=b[j]) {flag=0;break;} 16 if(flag) return cnt; 17 } 18 return 0; 19 } 20 void dfs(int i,int len) { 21 int flag=1; 22 for(int j=1;j<=n;++j) { 23 if(vis[j]>=2) continue; 24 if(!ccnt[i][j]) continue; 25 if(ccnt[i][j]==(int)s[i].length()||ccnt[i][j]==(int)s[j].length()) continue; 26 flag=0; 27 ++vis[j]; 28 dfs(j,len+s[j].length()-ccnt[i][j]); 29 --vis[j]; 30 } 31 if(flag&&len>ans) ans=len; 32 } 33 int main() { 34 scanf("%d",&n); 35 for(int i=1;i<=n;++i) cin>>s[i]; 36 for(int i=1;i<=n;++i) 37 for(int j=1;j<=n;++j) 38 ccnt[i][j]=con(s[i],s[j]); 39 while((c=getchar())==' '||c==' '||c==' '); 40 for(int i=1;i<=n;++i) if(s[i][0]==c) { 41 ++vis[i]; 42 dfs(i,s[i].length()); 43 --vis[i]; 44 } 45 printf("%d",ans); 46 return 0; 47 }