原题网址
由于某些原因,这个网址会进不去…
题目描述
单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如 b e a s t beast beast和 a s t o n i s h astonish astonish,如果接成一条龙则变为 b e a s t o n i s h beastonish beastonish,另外相邻的两部分不能存在包含关系,例如 a t at at和 a t i d e atide atide间不能相连。
格式
输入格式
输入的第一行为一个单独的整数 n ( n ≤ 20 ) n(n\le20) n(n≤20)表示单词数,以下 n n n行每行有一个单词,输入的最后一行为一个单个字符,表示“龙”开头的字母,你可以假定以此字母开头的“龙”一定存在。
输出格式
只需输出以此字母开头的最长的“龙”的长度。
样例
输入样例
5
at
touch
cheat
choose
tact
a
输出样例
23
(连成的“龙”为 a t o u c h e a t a c t a c t o u c h o o s e atoucheatactactouchoose atoucheatactactouchoose)
解题思路
这道题是一道 d f s dfs dfs深度优先搜索题,dfs需要以下几个形参:int dep表示现在已经连了几个单词,s表示当前字符串,int used[]表示每个单词用了几次。此外就是string的函数运用了。
Code
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
int n, maxs;
string str[21], ch;
void input()
{
cin>>n;
for (int i = 1; i <= n; i ++) cin>>str[i];
cin>>ch;
}
void dfs(int dep, string s, int used[]) // dep表示连了几个单词,s表示当前字符串,used[]表示每个单词用了几次
{
if (s.size() > maxs) maxs = s.size();
if (dep == 1)
{
for (int i = 1; i <= n; i ++) if (str[i][0] == s[0])
{
used[i] ++;
dfs(dep + 1, str[i], used);
used[i] --;
}
}
else
{
for (int i = 1; i <= n; i ++) if (used[i] < 2) for(int j = 1; j < str[i].size() && j < s.size(); j ++)
{
string s1 = str[i].substr(0, j);
if (s1 == s.substr(s.size() - j, j))
{
used[i] ++;
dfs(dep + 1, s + str[i].substr(j, str[i].size() - j), used);
if (used[i] < 2 && str[i][0] == str[i][str[i].size()-1]) // 判断能否连两次
{
used[i] ++;
dfs(dep + 1, s + str[i].substr(j, str[i].size() - j) + str[i].substr(1, str[i].size() - 1), used);
used[i] --;
}
used[i] --;
}
}
}
}
void output()
{
cout<<maxs;
}
int main()
{
input();
int m[21];
memset(m, 0, sizeof(m)); // m数组清零
dfs(1, ch, m);
output();
return 0;
}
大功告成 ∼ \sim ∼