信息学奥赛一本通 1220:单词接龙 搜索与回溯算法
单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如beast和astonish,如果接成一条龙则变为beastonish,另外相邻的两部分不能存在包含关系,例如at和atide间不能相连。你可以假定以此字母开头的“龙”一定存在。时间限制:
·
1220:单词接龙
时间限制: 1000 ms 内存限制: 65536 KB
【题目描述】
单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如beast和astonish,如果接成一条龙则变为beastonish,另外相邻的两部分不能存在包含关系,例如at和atide间不能相连。
【输入】
输入的第一行为一个单独的整数n(n<=20)表示单词数,以下n行每行有一个单词(只含有大写或小写字母,长度不超过20),输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在。
【输出】
只需输出以此字母开头的最长的“龙”的长度。
【输入样例】
5
at
touch
cheat
choose
tact
a
【输出样例】
23
解析:深度优先搜索,详见代码:
#include<bits/stdc++.h>
using namespace std;
int n;
int ans = 0;
string s[25];//s[i]:单词列表第i个单词
int vis[25];//vis[i]:单词s[i]用了几次
void dfs(string ls, int len) { //ls:当前龙中最后字符串,len为当前龙的长度
ans = max(ans, len); //取可能的最大的长度
for(int i = 1; i <= n; i++) {
if(vis[i] < 2) { //只要用了不足2次
//由于重合部分不能包含单词,所以重合部分长度要小于两单词的长度
for(int j = 1; j < ls.length() && j < s[i].length(); j++) {
//将ls末尾len个字符截取出来,看和s[i]前len个字符是否相同
//只要找到一个可以接上的情况,就不再找了,再找到的不会是最长的龙
if(ls.substr(ls.length() - j, j) == s[i].substr(0, j)) {
vis[i]++;//s[i]多用了1次
dfs(s[i], len + s[i].length() - j); //继续深搜
vis[i]--;//s[i]少用了1次
break;
}
}
}
}
}
int main() {
char st;//起始字符
cin >> n;
for(int i = 1; i <= n; i++) {
cin >> s[i];
}
cin >> st;
for(int i = 1; i <= n; i++) { //枚举每个单词
if(s[i][0] == st) { //如果起始字符和s[i]首字符相同
vis[i]++;//使用增加一次
dfs(s[i], s[i].length()); //以s[i]起始深搜
vis[i]--;//使用减少一次
}
}
cout << ans;
return 0;
}
更多推荐
所有评论(0)