(碎碎念:初二的时候就开始写这道题,写了几天觉得啊好烦啊就不想写就放弃了,上初三之后终于抽出时间把这个题写完了
(搜索题要我狗命(缩成一团
题目链接:
https://www.luogu.com.cn/problem/P1019
题目描述
单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如 beast和astonish,如果接成一条龙则变为beastonish,另外相邻的两部分不能存在包含关系,例如at 和 atide 间不能相连。
输入格式
输入的第一行为一个单独的整数n (n≤20)表示单词数,以下n 行每行有一个单词,输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在.
输出格式
只需输出以此字母开头的最长的“龙”的长度
分析
由于题目中给出的数据范围单词数n<=20很小,可以用搜索dfs去解决
按照给出的字母,我们先确定好一个单词作为开头
枚举剩下的且使用没有超过两次的单词
对于每一个单词再枚举他的与前面单词相接位数并判断是否可行(要注意一个单词并不能完全包含在另一个单词中)。
如果他可以接在前一个单词上,
就先将它接入后增加的位数累加进最后的答案中,再去搜索下一个可以接上的单词。
边界状态:
当一个单词后无法再接入任何一个单词
我们就把答案与之前得到的最大答案进行比较取两者中最大值。
AC Code
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
int read(){
int a = 0,f = 0;char p = getchar();
while(!isdigit(p)){f|=p=='-';p = getchar();}
while(isdigit(p)){a = (a<<3) + (a<<1) + (p^48);p = getchar();}
return f?-a:a;
}
char c[25][100];//存单词
int ans;//记录每一种情况的答案
int flag[10000];//标记这个单词已经用过次数
int Ans,n; //统计最终的答案 读入单词个数
bool Flag = 0;//判断一个单词后面是否还可以继续接入单词
void dfs(int x){//dfs!
Flag = 0;
for(int i = 1;i <= n;i ++){//尝试把i接在x的后面
if(flag[i] == 2)continue;
int leni = strlen(c[i]),lenx = strlen(c[x]);//记录两个单词长度
int cd = min(leni,lenx)-1;//最多能接在一起的长度为两个单词长度最小值-1
int cd1,tot;
int jl = 1;//记录我们想要接入几位
while(jl <= cd){
cd1 = jl,tot = 0;
//int now = 0;
while(cd1){//目前判断到的位置
if(c[x][lenx-cd1] != c[i][jl-cd1])break;
else tot++;
cd1--;
}
if(tot == jl)break;//两个可以接在一起
jl++;
}
if(tot == jl && tot != 0){//记录下来并且去搜索下一个
//cout<<x<<" "<<i<<" "<<tot<<endl;
Flag = 1;
ans += (leni-jl);
flag[i] ++;
dfs(i);
ans -= (leni-jl);
flag[i] --;
}
}
if(Flag == 0){//后面什么也没法接的时候
Ans = max(ans,Ans);
}
}
int main(){
n = read();
for(int i = 1;i <= n;i++)
scanf("%s",&c[i]);
char a;
cin >> a;
for(int i = 1;i <= n;i++){
if(c[i][0] == a){
//cout<<c[i]<<endl;
flag[i]++;
ans = strlen(c[i]);
dfs(i);
}
}
cout << Ans;
}
注意(不过可能也就我这么憨憨才会错的一个地方)
我们在枚举他可以接入的位数时,应该从小到大进行枚举,在能让两个单词相接的情况下,让相接的部分尽可能的小
比如:
abababab和abababc
如果我们从大到小枚举它可以接入的部分那么最后相接就会变为
ababababc 有9位
但我们从小到大枚举得到的才是最长的情况
ababababababc 有13位