蓝桥杯 算法提高 单词接龙 _DFS_搜索 字符串比较

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <queue>
using namespace std;

const int maxn = 20 + 10;
int n;
int ans;
char ch;
string dick[maxn];
int use[maxn];
void input();
int check(int lh, int rh);
void dfs(int cur, int len, bool first);
void solve();

void input(int n)
{
    memset(use, 0, sizeof(use));
    for (int i = 0; i < n; i++) {
        cin >> dick[i];
    }
    cin >> ch;
}

int check(int lh, int rh)
{
    int l_l = dick[lh].size(),
        r_l = dick[rh].size();
    bool flag;

    //k: 这是"下一个字符串"的索引
    for (int k = 1; k < min(l_l, r_l); k++)
    {
        flag = true;
        // i: 这是"前一个字符串"
        // i = l_l - k,代表后面的字符已经匹配,
        //正在尝试向前匹配寻找更长的匹配长度
        // j--下一个字符串匹配索引
        for (int i = l_l - k , j = 0; i < l_l && j < k; i++, j++)
        {
            if (dick[lh][i] != dick[rh][j]) {
                flag = false;
                break;
            }
        }
        //k为前一个字符串尾部向前和下一个字符串头部向后匹配的长度
        if (flag) return k;
    }
    //没有在里面退出,说明是包含关系 or 不重复
    return 0;
}

//last--下一个字符串索引, len -- 当前已经计算了的字符串长度
void dfs(int last, int len, bool first)
{
    if (first)                   //第一次的时候 从这里开始(需要找 ch 开头的字符串)
    {
        for (int i = 0; i < n; i++) {
            if (dick[i][0] == ch) {
                if (use[i] < 2)  //使用没有超过两次
                {
                    use[i]++;
                    //从开头字符是 ch 的字符串开始递归搜索
                    //将first标志false
                    dfs(i, dick[i].size(), false);
                    use[i]--;
                }
            }
        }
    }
    else {
        //从搜索的组合中, 不断更新得到最大长度
        ans = max(ans, len);
        for (int i = 0; i < n; i++)
        {
            //上一个字符串尾部和下一个字符串开头,
            //匹配的长度
            int x = check(last, i);
            //有匹配, 且字符串使用不超过2次
            if (x && use[i] < 2) {
                use[i]++;
                // 已经计算的长度 + 当前字符串长度 - 重复的长度 ==> 得到当前总长度
                dfs(i, len + dick[i].size() - x, false);
                use[i]--;
            }
        }
    }
}

void solve()
{
    scanf("%d", &n);
    input(n);
    dfs(0, 1, true);
    cout << ans << endl;
}

int main()
{
    //测试check函数
//    cin >> dick[0] >> dick[1];
//    cout << "debug = " << check(0, 1) << endl;
    solve();
    return 0;
}

个人总结:

通常DFS的题目,需要先写下如下模板:

const int maxn = 20 + 10;
int n;
int ans;
char ch;
string dick[maxn];
int use[maxn];    //通常这个,好多DFS题目都会用到的,用来标志使用情况,这里作用是标志使用<2次的情况
void input();     //输入数据
int check(int lh, int rh);   //这个几乎也是都会用到的,用来检查DFS进行的条件,以及相关操作
void dfs(int cur, int len, bool first);  //这个当然必须写了
void solve();     //程序的启动函数....

还有就是回溯的使用,通常要从搜索中寻找到最优的解,或者是寻找所有解,需要每一种情况搜索完之后,要恢复原来的值,

递归语句就放在 标志标志数组 和 去除标志数组 之间如:

     ans = max(ans, len);
        for (int i = 0; i < n; i++)
        {
            //上一个字符串尾部和下一个字符串开头,
            //匹配的长度
            int x = check(last, i);
            //有匹配, 且字符串使用不超过2次
            if (x && use[i] < 2) {
                use[i]++;
                // 已经计算的长度 + 当前字符串长度 - 重复的长度 ==> 得到当前总长度
                dfs(i, len + dick[i].size() - x, false);
                use[i]--;
            }
        }
时间: 2024-08-06 11:49:07

蓝桥杯 算法提高 单词接龙 _DFS_搜索 字符串比较的相关文章

蓝桥杯——算法提高 最小方差生成树

一.思路 枚举所有生成树的边权和值,对每一个枚举的边权和值sum,修改所有边的边权为(es[i].cost - sum * 1.0 / (N - 1))2,即方差公式的分子,然后跑最小生成树算法,同时记录边的原来的权值和,如果求出的“最小方差”生成树的边权值和为sum,那么,用这个"最小方差"去更新答案. 二.复杂度分析 时间复杂度:O(N * W * M * logM).N * W为枚举边权和值的时间.边权和值最小为0,最大为(N - 1) * W. 三.PS 这题据说蓝桥杯官网数据

蓝桥杯 算法提高 6-17 复数四则运算

算法提高 6-17复数四则运算 时间限制:1.0s   内存限制:512.0MB 设计复数库,实现基本的复数加减乘除运算. 输入时只需分别键入实部和虚部,以空格分割,两个复数之间用运算符分隔:输出时按a+bi的格式在屏幕上打印结果.参加样例输入和样例输出. 注意考虑特殊情况,无法计算时输出字符串"error". 样例输入 2 4 * -3 2 样例输出 -14-8i 样例输入 3 -2 + -1 3 样例输出 2+1i 1 #include<iostream> 2 #inc

蓝桥杯 算法提高 8皇后&#183;改 -- DFS 回溯

  算法提高 8皇后·改   时间限制:1.0s   内存限制:256.0MB 问题描述 规则同8皇后问题,但是棋盘上每格都有一个数字,要求八皇后所在格子数字之和最大. 输入格式 一个8*8的棋盘. 输出格式 所能得到的最大数字和 样例输入 1 2 3 4 5 6 7 89 10 11 12 13 14 15 1617 18 19 20 21 22 23 2425 26 27 28 29 30 31 3233 34 35 36 37 38 39 4041 42 43 44 45 46 47 48

蓝桥杯 算法提高 道路和航路 满分AC ,SPFA算法的SLF优化,测试数据还是比较水的,貌似没有重边

算法提高 道路和航路 时间限制:1.0s   内存限制:256.0MB 问题描述 农夫约翰正在针对一个新区域的牛奶配送合同进行研究.他打算分发牛奶到T个城镇(标号为1..T),这些城镇通过R条标号为(1..R)的道路和P条标号为(1..P)的航路相连. 每一条公路i或者航路i表示成连接城镇Ai(1<=A_i<=T)和Bi(1<=Bi<=T)代价为Ci.每一条公路,Ci的范围为0<=Ci<=10,000:由于奇怪的运营策略,每一条航路的Ci可能为负的,也就是-10,000

蓝桥杯 算法提高 学霸的迷宫 经典BFS问题

算法提高 学霸的迷宫 时间限制:1.0s   内存限制:256.0MB 问题描述 学霸抢走了大家的作业,班长为了帮同学们找回作业,决定去找学霸决斗.但学霸为了不要别人打扰,住在一个城堡里,城堡外面是一个二维的格子迷宫,要进城堡必须得先通过迷宫.因为班长还有妹子要陪,磨刀不误砍柴功,他为了节约时间,从线人那里搞到了迷宫的地图,准备提前计算最短的路线.可是他现在正向妹子解释这件事情,于是就委托你帮他找一条最短的路线. 输入格式 第一行两个整数n, m,为迷宫的长宽. 接下来n行,每行m个数,数之间没

蓝桥杯-算法提高-日期计算

算法提高 日期计算 时间限制:1.0s   内存限制:256.0MB 问题描述 已知2011年11月11日是星期五,问YYYY年MM月DD日是星期几?注意考虑闰年的情况.尤其是逢百年不闰,逢400年闰的情况. 输入格式 输入只有一行 YYYY MM DD 输出格式 输出只有一行 W 数据规模和约定 1599 <= YYYY <= 2999 1 <= MM <= 12 1 <= DD <= 31,且确保测试样例中YYYY年MM月DD日是一个合理日期 1 <= W &

蓝桥杯- 算法提高 逆序排列

算法提高 逆序排列 时间限制:1.0s   内存限制:512.0MB 问题描述 编写一个程序,读入一组整数(不超过20个),并把它们保存在一个整型数组中.当用户输入0时,表示输入结束.然后程序将把这个数组中的值按逆序重新存放,并打印出来.例如:假设用户输入了一组数据:7 19 -5 6 2 0,那么程序将会把前五个有效数据保存在一个数组中,即7 19 -5 6 2,然后把这个数组中的值按逆序重新存放,即变成了2 6 -5 19 7,然后把它们打印出来. 输入格式:输入只有一行,由若干个整数组成,

蓝桥杯- 算法提高 最大乘积

算法提高 最大乘积 时间限制:1.0s   内存限制:512.0MB 问题描述 对于n个数,从中取出m个数,如何取使得这m个数的乘积最大呢? 输入格式 第一行一个数表示数据组数 每组输入数据共2行: 第1行给出总共的数字的个数n和要取的数的个数m,1<=n<=m<=15, 第2行依次给出这n个数,其中每个数字的范围满足:a[i]的绝对值小于等于4. 输出格式 每组数据输出1行,为最大的乘积. 样例输入 15 51 2 3 4 2 样例输出 48 #include<iostream&

java 蓝桥杯算法提高 字串统计

思路:这道题用HashMap来保存枚举的字串,key值保存字串-value值保存字串所出现的次数:         通过for循环并使用subString()方法枚举所有符合要求的子串maxStr记录出现次数最多的字串,          maxValue记录其出现的次数 1截取到的长度大于等于l的子串先比较是否已经存在map里, 1.1若存在,取出它的次数并+1.和最大次数比较 1.1.1若大于最大次数,将这个次数赋给最大次数,并且将子串赋给最大次数的子串 1.1.2若等于最大次数,再判断这两