洛谷P1019题解
题目链接:https://www.luogu.com.cn/problem/P1019
分析题目,有以下几个比较重要的条件:
1.每个单词最多出现两次。这里我们要开一个vis数组,当出现的数字>=2(vis[x]>=2)时,就不用做了。
2.两个单词重叠部分不固定。这意味着我们要单独开一个函数判断是否可以相连。
3.任意两个单词不能重叠(如at和atabc不可以)。emmm.....其实这个条件是没用的最多有点剪枝的效果,但数据并没有卡这个条件((
程序思路:
1.把任意两个单词的最小重叠部分储存到num数组中。
2.找开头为ch的单词(ch为龙头)
3.进行深搜
其他见程序:
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,an,ans,vis[50],num[50][50]; 4 string s[50]; 5 char ch; 6 int number(string a,string b){//a和b的最小重叠部分 7 int lena=a.size(),tx,ty=0;//tx表示a的下标,ty表示b的下标 8 for(int k=lena-1;k>=0;--k){ 9 int check=1; 10 for(int tx=k;tx<=lena-1;++tx){ 11 if(a[tx]!=b[ty++]){ 12 check=0; 13 break; 14 } 15 } 16 if(check)return a.size()-k; 17 ty=0; 18 } 19 return 0; 20 } 21 void dfs(int p){//深搜,表示当前搜到了第p个位置 22 int check=1; 23 for(int i=1;i<=n;++i){ 24 if(vis[i]>=2)continue;//使用次数>=2 25 if(num[p][i]==0)continue;//没有重叠部分 26 vis[i]++;//使用次数+1 27 an+=s[i].size()-num[p][i];//答案+单词长度-重叠部分长度 28 check=0; 29 dfs(i); 30 an-=s[i].size()-num[p][i]; 31 vis[i]--; 32 } 33 if(check)ans=max(ans,an);//当是龙的末尾单词时,计算龙的长度 34 } 35 int main(){ 36 cin>>n; 37 for(int i=1;i<=n;++i)cin>>s[i]; 38 cin>>ch; 39 for(int i=1;i<=n;++i) 40 for(int j=1;j<=n;++j){ 41 num[i][j]=number(s[i],s[j]); 42 // cout<<i<<" "<<j<<" "<<num[i][j]<<endl; 43 }//把最小重叠部分扔进num数组里 44 for(int i=1;i<=n;++i){ 45 if(s[i][0]==ch){//找单词开头为龙头的单词 46 memset(vis,0,sizeof(vis)); 47 vis[i]=1; 48 an=s[i].size(); 49 dfs(i); 50 } 51 } 52 cout<<ans<<endl; 53 return 0; 54 }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步