单词接龙(DFS)
2017-09-09 11:53
393 查看
题目描述 Description
单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如beast和astonish,如果接成一条龙则变为beastonish,另外相邻的两部分不能存在包含关系,例如at和atide间不能相连。
输入描述 Input Description
输入的第一行为一个单独的整数n(n<=20)表示单词数,以下n行每行有一个单词,输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在。
输出描述 Output Description
只需输出以此字母开头的最长的“龙”的长度
样例输入 Sample Input
样例输出 Sample Output
数据范围及提示 Data Size & Hint
限制
时间限制: 1 s
空间限制: 128000 KB
个人思路
1、有两种情况,龙头和非龙头,龙头情况最为简单,判断第一个字符是否相同即可。
2、非龙头的情况,先判断使用次数是否达到2次了,如果不是,则比较当前选中的字符串和龙字符串,找到最长的相同部分拼接即可,当然还要满足非包含关系。
3、遍历完所有情况就能找到最长的那条龙。
个人总结
这是2000年NOIP全国联赛普及组NOIP全国联赛提高组的一道题,确实有点麻烦。
说一下处理过程中的一些问题吧。
问题一: 传参
龙传递的过程中是不断在改变的,所以必须保留之前的龙,等下一层调用完成时,回退龙, 并且回退使用次数。这个问题是后来测试错误才发现的。
问题二:如何找到当前选中的字符串与龙头最大重叠部分,并且保证不是包含关系。
我是这样处理的,为了描述简单,设当前选中的字符串为s1,龙字符串为s2。
尝试一个字母相同、两个字母相同、三个字母相同……,直到min(strlen(s1),strlen(s2))相同为止。
pre记录前一种情况是否相同,now记录当前情况是否相同。当pre=true,now=false,则说明pre那种情况是s1和s2最长重叠部分,此时也保证了两者之间不是包含关系。
单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如beast和astonish,如果接成一条龙则变为beastonish,另外相邻的两部分不能存在包含关系,例如at和atide间不能相连。
输入描述 Input Description
输入的第一行为一个单独的整数n(n<=20)表示单词数,以下n行每行有一个单词,输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在。
输出描述 Output Description
只需输出以此字母开头的最长的“龙”的长度
样例输入 Sample Input
5 at touch cheat choose tact a
样例输出 Sample Output
23
数据范围及提示 Data Size & Hint
(连成的“龙”为atoucheatactactouchoose)
限制
时间限制: 1 s
空间限制: 128000 KB
个人思路
1、有两种情况,龙头和非龙头,龙头情况最为简单,判断第一个字符是否相同即可。
2、非龙头的情况,先判断使用次数是否达到2次了,如果不是,则比较当前选中的字符串和龙字符串,找到最长的相同部分拼接即可,当然还要满足非包含关系。
3、遍历完所有情况就能找到最长的那条龙。
#include<cstdio> #include<cstring> #include<iostream> using namespace std; short n; int Maxstr=0; char a[21][30];//储存输入 int book[30];//标记,记录使用次数 void DFS(char str[])//str[]为当前的龙 { char str2[500]; if(strlen(str)>Maxstr) { Maxstr=strlen(str); } for(int i=1;i<=n;i++) { if(strlen(str)==1&&a[i][0]==str[0])//接入龙头 { strcpy(str2,str); int k=1; int j=1; while(j<strlen(a[i])) str[k++]=a[i][j++]; str[k]='\0'; book[i]++; DFS(str); //回退!! strcpy(str,str2); book[i]--; } else if(book[i]<2) { bool flag=false; bool now,pre=false; int k; int temp=min(strlen(str),strlen(a[i])); for(k=1;k<=temp;k++)//比较所有情况,一个字母相同,两个字母相同…… { now=true; int k1=0; int k2=strlen(str)-k; for(int j=0;j<k;j++) { if(str[k2++]!=a[i][k1++]) { now=false; break; } } if(!now&&pre)//之前情况满足,现在不满足了,说明现在是字母最多的情况了,并且关系为不包括 { flag=true; break; } pre=now; } if(flag) { strcpy(str2,str); int m=strlen(str); --k;//下标是从0开始的 while(k<strlen(a[i])) str[m++]=a[i][k++]; str[m]='\0'; book[i]++; DFS(str); //回退!! strcpy(str,str2); book[i]--; } } } } int main() { char c; char str[1000]; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%s",&a[i]); //此处使用scanf("%c",&c)的话,会出错,printf("c:%d",c);得到的10,'\n'的ASCII码,是获取之前的一个回车符,故使用cin>>c; cin>>c; for(int i=0;i<30;i++) book[i]=0; str[0]=c; str[1]='\0'; DFS(str); printf("%d\n",Maxstr); return 0; }
个人总结
这是2000年NOIP全国联赛普及组NOIP全国联赛提高组的一道题,确实有点麻烦。
说一下处理过程中的一些问题吧。
问题一: 传参
龙传递的过程中是不断在改变的,所以必须保留之前的龙,等下一层调用完成时,回退龙, 并且回退使用次数。这个问题是后来测试错误才发现的。
问题二:如何找到当前选中的字符串与龙头最大重叠部分,并且保证不是包含关系。
我是这样处理的,为了描述简单,设当前选中的字符串为s1,龙字符串为s2。
尝试一个字母相同、两个字母相同、三个字母相同……,直到min(strlen(s1),strlen(s2))相同为止。
pre记录前一种情况是否相同,now记录当前情况是否相同。当pre=true,now=false,则说明pre那种情况是s1和s2最长重叠部分,此时也保证了两者之间不是包含关系。
相关文章推荐
- 蓝桥杯 单词接龙(dfs)
- code1018 单词接龙 dfs,字符串处理
- DFS - 单词接龙
- NOIP2000单词接龙[DFS]
- P1019 单词接龙【DFS+字符串】
- luogu P1019 单词接龙 【dfs】
- codevs1018 单词接龙(DFS)
- codevs1018 单词接龙(DFS)
- 1172: 单词接龙(XCOJ 暴力DFS)
- 算法训练 单词接龙(dfs)
- codevs 天梯 单词接龙 DFS
- 蓝桥杯算法训练单词接龙(DFS)java实现
- CODEVS 1018 单词接龙(DFS)
- DFS——[ 2000Noip提高组第三题 ]单词接龙
- 单词接龙(dfs)
- ALGO-18 单词接龙 —— DFS与字符串处理(java)
- Codevs 1018 单词接龙 DFS --2000年NOIP全国联赛普及组NOIP全国联赛提高组
- 单词接龙(dfs)
- [luoguP1019] 单词接龙(DFS)
- 洛谷 P1019 单词接龙【经典DFS,温习搜索】