_YueYang

导航

洛谷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 }

 

posted on 2020-04-26 21:11  _YueYang  阅读(286)  评论(0编辑  收藏  举报