题目传送门

当时一看到这题,蒟蒻的我还以为是DP,结果发现标签是搜索……

这道题的难点在于思路和预处理,真正的搜索实现起来并不难。我们可以用一个贪心的思路,开一个dic数组记录每个单词的最小重复部分,这样搜索的时候就可以很方便地查阅dic数组,而不是每次再计算一遍。
预处理是长这样子的:

void f(string a,string b,int x,int y)
{
    int a1=a.size()-1,b1=b.size()-1;
    for(int i=0;i<=b1;i++)  //从第一个开始枚举
    {
        if(a[0]==b[i])  //如果a的首字母和b中间的字母相同 ,则判断它们能不能接在一起
        {
            int pos=0,tot=0;  //pos是当前a的第几个字母,tot是a和b的重合部分长度
            for(int j=i;j<=b1;j++)
            {
                if(a[pos]==b[j])
                {
                    tot++;
                    pos++;
                    if(j==b1&&tot!=min(a1,b1)+1) //如果枚举到了最后,并且a和b没有包含关系,说明可以这么接
                      dic[x][y]=tot;  //记录最小重叠部分的长度
                                      //之所以不break,是因为后面可能还会枚举到更小的接法
                                      //比如 chsese 和 sesettt 显然 chsesesettt 要比chsesettt更优
                }
                else break;
            }
        }
    }
}

这样就把每个单词的相互重叠部分全记录下来了,最后的处理出来的dic[x][y]是把x接在y后面的重复部分长度

之后我们就可以愉快的搜索了,搜索本身并不难,只需要注意每个单词可以用两次,以及接上新单词的“龙”的长度就可以了。

完整代码:

#include<iostream>
using namespace std;
int n,dic[21][21],vis[21],ans;
string words[21];
char s;
void f(string a,string b,int x,int y)
{
    int a1=a.size()-1,b1=b.size()-1;
    for(int i=0;i<=b1;i++)  //从第一个开始枚举
    {
        if(a[0]==b[i])  //如果a的首字母和b中间的字母相同 ,则判断它们能不能接在一起
        {
            int pos=0,tot=0;  //pos是当前a的第几个字母,tot是a和b的重合部分长度
            for(int j=i;j<=b1;j++)
            {
                if(a[pos]==b[j])
                {
                    tot++;
                    pos++;
                    if(j==b1&&tot!=min(a1,b1)+1) //如果枚举到了最后,并且a和b没有包含关系,说明可以这么接
                      dic[x][y]=tot;  //记录最小重叠部分的长度
                                      //之所以不break,是因为后面可能还会枚举到更小的接法
                                      //比如 chsese 和 sesettt 显然 chsesesettt 要比chsesettt更优
                }
                else break;
            }
        }
    }
}
void dfs(int pos,int sum)
{
    ans=max(ans,sum);  //实时更新ans
    for(int i=1;i<=n;i++)
    {
        if(dic[i][pos]&&vis[i])
        {
            vis[i]--;
            int suml=sum+words[i].size()-dic[i][pos]; //接上新单词"龙"的长度为=旧的长度+新单词长度-重复部分长度
            dfs(i,suml);  //接上新单词继续搜索
            vis[i]++;
        }
    }
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>words[i];
        vis[i]=2; //初始化vis数组,每个单词能用两次
    }
    cin>>s;
    for(int i=1;i<=n;i++)
      for(int j=1;j<=n;j++)
        f(words[i],words[j],i,j); //预处理dic数组 

    for(int i=1;i<=n;i++)
    {
        if(words[i][0]==s)  //找到开始部分
        {
            vis[i]--;
            dfs(i,words[i].size()); //深搜
            vis[i]++;
        }
    }
    cout<<ans;

    return 0;
}
  • 广告时间

在下的洛谷博客博客园博客

洛谷 P1019 单词接龙 (DFS)的更多相关文章

  1. 洛谷 P1019 单词接龙【经典DFS,温习搜索】

    P1019 单词接龙 题目描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在 ...

  2. 洛谷 P1019 单词接龙 Label:dfs

    题目描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合 ...

  3. 洛谷P1019——单词接龙(DFS暴力搜索)

    https://www.luogu.org/problem/show?pid=1019#sub 题目描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母, ...

  4. 洛谷 p1019 单词接龙

    题目描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合 ...

  5. [NOIP2000] 提高组 洛谷P1019 单词接龙

    题目描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合 ...

  6. 洛谷——P1019 单词接龙(NOIP2000 T3)

    https://www.luogu.org/problem/show?pid=1019#sub 题目描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母, ...

  7. 洛谷P1019 单词接龙题解(超详细注释)

    https://www.luogu.org/problem/P1019 #include<cstdio> #include<cstring> #include<iostr ...

  8. 洛谷 P1019单词接龙

    看吧,多简单啊,没有人受伤的世界完成了.                                                                                ...

  9. 洛谷1019 单词接龙 字符串dfs

    问题描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合 ...

随机推荐

  1. HDU5908【模拟】

    思路: 找到约数k,然后算一下1-k区间里的数的个数. 中间交换一下就好了,然后把后面每个区间里的数减减,然后再判断一下满足不满足= = #include <bits/stdc++.h> ...

  2. 简单实现TabBar的自定义

    StackoverFlow上看到的,通过继承UITabBarController创建自定义TabBarController.在原有TabBar的基础上添加一个背景层,在其基础上增加三个自定义按钮,通过 ...

  3. iReport - 无法正常启动的解决方法

    问题与分析 最近需要用到iReport报表工具,但是在启动客户端时却发现只出现了启动界面,很快就界面消失没反应了.反复打开了好几次客户端,都无法正常打开.问了下同事,说是因为jdk升级的原因,以前项目 ...

  4. window git bash客户端vimrc设置tab缩进

    从开发机写的代码,弄到windows上的客户端git提交,总是显示格式对不起的问题,问题是再vimrc上tab键的缩进不等于4个空格,然后就需要设置成和linux一样的四格缩进. 安装上git bas ...

  5. UWP 保存用户设置

    一:需求 需要保存用户设置,用户下一次再打开app时,加载默认的设置.比如用户设置的主题颜色,用户自定义的文件保存路径等. 一般应用的的数据存储分为两种,一种是云存储(将数据保存在云端,下次打开的时候 ...

  6. tensorflow:实战Google深度学习框架第四章02神经网络优化(学习率,避免过拟合,滑动平均模型)

    1.学习率的设置既不能太小,又不能太大,解决方法:使用指数衰减法 例如: 假设我们要最小化函数 y=x2y=x2, 选择初始点 x0=5x0=5  1. 学习率为1的时候,x在5和-5之间震荡. im ...

  7. zh-cn、en-us、zh-tw等表示语言(文化)代码与国家地区对照表(最全的各国地区对照表)

    af 公用荷兰语 af-ZA 公用荷兰语 - 南非 sq 阿尔巴尼亚 sq-AL 阿尔巴尼亚 -阿尔巴尼亚 ar 阿拉伯语 ar-DZ 阿拉伯语 -阿尔及利亚 ar-BH 阿拉伯语 -巴林 ar-EG ...

  8. Python常用模块之hashlib(加密)

    Python常用模块之hashlib(加密) Python里面的hashlib模块提供了很多加密的算法,这里介绍一下hashlib的简单使用事例,用hashlib的md5算法加密数据import ha ...

  9. 530 Minimum Absolute Difference in BST 二叉搜索树的最小绝对差

    给定一个所有节点为非负值的二叉搜索树,求树中任意两节点的差的绝对值的最小值.示例 :输入:   1    \     3    /   2输出:1解释:最小绝对差为1,其中 2 和 1 的差的绝对值为 ...

  10. 104 Maximum Depth of Binary Tree 二叉树的最大深度

    给定一个二叉树,找出其最大深度.二叉树的深度为根节点到最远叶节点的最长路径上的节点数.案例:给出二叉树 [3,9,20,null,null,15,7],    3   / \  9  20    /  ...