P1019
题目描述
单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如
beast和astonish,如果接成一条龙则变为beastonish,另外相邻的两部分不能存在包含关系,例如at和
atide 间不能相连。
输入输出格式
输入格式:
输入的第一行为一个单独的整数n (n≤20)表示单词数,以下n
行每行有一个单词,输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在.
输出格式:
只需输出以此字母开头的最长的“龙”的长度
输入样例:
5
at
touch
cheat
choose
tact
a
输出样例:
23
说明:
连成的龙为atoucheatactactouchoose
.
解题思路:
把它转化成二叉树,然后dfs就可以了
具体方式如下(不全,注意思想就好了):
黄色部分就是最长的了。
这道题最关键的不是dfs,而是我们如何找到下一步要接龙的头。也就是要如何找到两个单词最小重叠部分。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| int min_cover_word(int x,int y) { bool p=true; int y_start=0; for(int k=str[x].size()-1;k>=0;k--){ for(int x_start=k; x_start<str[x].size();x_start++){ if(str[x][x_start] != str[y][y_start++]){ p=false; break; } } if(p==true) return str[x].size()-k; y_start=0; p=true; } return 0; }
|
这步可能不太容易理解,可以在草稿中模拟一下就清楚了。
AC代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
| #include <iostream> #include <cstring> #include <cmath> #include <cstdio> #include <algorithm> #include <vector> #define ll long long using namespace std;
string str[100]; int vis[100]; int n,ans=-1,now=0; int min_cover[100][100]; char ch;
int min_cover_word(int x,int y) { bool p=true; int y_start=0; for(int k=str[x].size()-1;k>=0;k--){ for(int x_start=k; x_start<str[x].size();x_start++){ if(str[x][x_start] != str[y][y_start++]){ p=false; break; } } if(p==true) return str[x].size()-k; y_start=0; p=true; } return 0; }
void dfs(int x) { bool jx=false; for(int i=1;i<=n;i++){ if(vis[i]>=2) continue; if(min_cover[x][i]==0) continue; if(min_cover[x][i]==str[x].size() || min_cover[x][i] == str[i].size()) continue; now += str[i].size()-min_cover[x][i]; vis[i]++; jx=true; dfs(i); now -= str[i].size()-min_cover[x][i]; vis[i]--; } if(jx==false) ans=max(ans,now); return; }
int main() { cin>>n; for(int i=1;i<=n;i++) cin>>str[i]; cin>>ch; for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ min_cover[i][j]=min_cover_word(i,j); } } for(int i=1;i<=n;i++){ if(str[i][0]==ch){ vis[i]++; now=str[i].size(); dfs(i); vis[i]=0; } } cout<<ans<<endl; return 0; }
|