原题链接
P1019
题目类型:
普
及
/
提
高
−
{\color{yellow} 普及/提高-}
普及/提高−
题目大意
给你
n
≤
20
n\le 20
n≤20个单词,让你串在一起,还规定单词串的开头字母为
c
c
c,每个单词最多用
2
2
2次,且相邻的两个单词不能是包含关系,求最长的单词串的长度。
S
a
m
p
l
e
\mathbf{Sample}
Sample
I
n
p
u
t
\mathbf{Input}
Input
5 //n
at
touch
cheat
choose
tact
a //c
S a m p l e \mathbf{Sample} Sample O u t p u t \mathbf{Output} Output
23
H i n t & E x p l a i n \mathbf{Hint\&Explain} Hint&Explain
最长的单词串为:atoucheatactactouchoose
解题思路
用 d f s dfs dfs,把所有的可能性遍历,并维护当前已经连成的单词串和刚才连到单词串上的单词,再处理一下合并的函数和判断是否可以连上的函数即可
上代码
#include<iostream>
using namespace std;
int n,used[30],res;
string s[30];
char sta;
bool exist(string word,string b)
{
// cout<<"exist:"<<word<<" "<<b<<endl;
int fin;
for(int i=1; i<word.size(); i++)
{
string str=word.substr(word.size()-i,i);
fin=b.find(str);
if(fin==0) return true;
}
return false;
}
string hebin(string a,string b)
{
// cout<<"hebin:"<<a<<" "<<b<<endl;
int fin,len=0;
do
{
len++;
string str=a.substr(a.size()-len,len);
// cout<<len<<" "<<str<<endl;
fin=b.find(str);
}while(fin!=0);
string str=a.substr(0,a.size()-len);
return str+b ;
}
void dfs(string tar,string last)
{
// cout<<tar<<" "<<last<<endl;
bool can=false;
for(int i=1; i<=n; i++)
if(used[i]<2&&exist(last,s[i]))
{
can=true;
used[i]++;
dfs(hebin(tar,s[i]),s[i]);
used[i]--;
}
if(!can)
{
int len=tar.size();
res=std::max(res,len);
// cout<<tar<<endl;
}
}
int main()
{
cin>>n;
for(int i=1; i<=n; i++) cin>>s[i];
cin>>sta;
for(int i=1; i<=n; i++)
{
if(s[i][0]==sta)
{
used[i]++;
dfs(s[i],s[i]);
used[i]--;
}
}
cout<<res<<endl;
// cout<<hebin(s[1],s[1])<<endl;
return 0;
}
完美切题 ∼ \sim ∼