把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

OpenJudge 2.5-8783 单词接龙

Description

单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如beast和astonish,如果接成一条龙则变为beastonish,另外相邻的两部分不能存在包含关系,例如at和atide间不能相连。
Input
输入的第一行为一个单独的整数n(n<=20)表示单词数,以下n行每行有一个单词(只含有大写或小写字母,长度不超过20),输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在。
Output
只需输出以此字母开头的最长的“龙”的长度。
Sample Input
5
at
touch
cheat
choose
tact
a
Sample Output
23

   在讲这道题之前,先说一点题外话:其实刚开始读到这道题的时候是抗拒的,所以一直没有去碰,后面是布置任务下来了才去做的,所以在面对一道题时不要有畏难情绪。其实这道题还是蛮简单的(虽然做了好久好久...)

   这种题一来果断string,用char的话就要定义二维,用string数组,一个元素就是一个单词。

   这道题据说有人是将龙全部接上去了的,我没有那么做,只计算了长度。思路就是回溯法,只不过最后那个判断外面要加一些东西:外层循环仍然枚举,枚举每一个单词,如果它的使用次数<2(需定义bool标记),就枚举被接龙单词的每一个字母,与接龙单词的首字母比较,找出接龙起点。记录下两个单词的接龙起点,再用while依次比对到被接龙单词末尾,如果while中被接龙单词的接龙起点到达了末尾(也就是说while循环到了最后,所有字母全都匹配,可以接龙),就开始接龙(回溯)。

    先奉上代码:

#include<cstdio>
#include<string>
#include<iostream>
#include<algorithm>
using namespace std;
string a[21];
int n,maxn,used[21],l=1;
void dfs(int c)//a[c]已定单词,a[i]接龙单词
{
    int lc,li;
    maxn=max(maxn,l);
    for(int i=1;i<=n;i++)
        if(used[i]<2)
        {
            for(int j=0;j<a[c].length();j++)//将已定单词的每一个字母逐一与接龙单词
                if(a[c][j]==a[i][0])//的首字母比较,从相同的地方开始接
                {
			lc=j;
			li=0;//记录接龙起点
                    while(a[c][lc]==a[i][li]&&lc<a[c].length())//逐个比对,如果相同且长度没超过已定单词的长度就累加长度
                    {
                        lc++;
                        li++;
                    }
                    if(lc==a[c].length())//如果比对到了,就接上长度(到达目标)
                    {
                        l+=a[i].length()-li;
                        used[i]++;
                        dfs(i);
                        l-=a[i].length()-li;
                        used[i]--;
                    }
                }
        }
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        cin>>a[i];
    cin>>a[n+1];
    dfs(n+1);//把头字母也当成一个单词,从头字母开始搜
    printf("%d",maxn);
} 

有几点需要特别说明的:

1.它是要求最长,前面找接龙起点可以倒序找,只要找到一个就break,我这么写也会找到,因为我虽然顺序查找但是没有break,所以最终还是会查找到,但是耗时要长一些。

2.找接龙起点以及接龙长度(就是包括while那一段)可以用a.substr(i,j)这个函数来做,i表示查找起点(位置),j表示长度。

3.有一个我想了很久但是很懵的问题:我把lc,li定义在dfs()里面就没问题,但是定义在外面就会错。刚开始以为是回溯递归会影响到值,但是每次找到接龙起点时都重新附了值。然后我对比了两种方法lc,li以及a[i].lengrh()-li的值,都一样,但只要加上l(l+=a[i].lengrh()-li那里),值就会错,甚至有负数。



posted @ 2017-07-07 17:41  Starlight_Glimmer  阅读(22)  评论(0编辑  收藏  举报  来源
浏览器标题切换
浏览器标题切换end