DFS深度优先搜索与回溯算法

news2024/9/24 17:19:15

目录

递归遍历的三步骤:

DFS/回溯模板 

 练习

1.三角形路径和最大搜索

 (一)前序DFS(从上至下搜索,实际是暴力解法,测试超时)

(二)后序DFS(自底向上搜索,设置memory数组记录各节点子树的最大路径和,相同子树剪枝优化,AC)

(1)递归无返回值

(2)递归有返回值


         DFS是一种遍历/搜索树和图的算法,感觉和回溯算法类似,思想都是沿着树的深度进行(按照前序/中序/后序)递归搜索,直至搜索到某一路径的叶节点(或满足某终止条件),后沿深度进行回溯,搜索其余路径。访问完所有可能路径后,返回目标任务最优解或所有满足条件的路径。

        这实际就是一种暴力解法,时间复杂度高,为了提高算法效率,可分析题目,结合记忆法等对树进行剪枝优化

递归遍历的三步骤:

1.递归函数的参数、返回值(每层递归需要处理的数据)

2.递归终止条件(终止条件错误总会导致操纵系统的内存栈溢出错误)

3.单层递归逻辑(每层递归需要执行的操作)

DFS/回溯模板 

void dfs(参数) {
    if (终止条件) {
        存放结果;
        return;
    }

    for (选择:本节点所连接的其他节点) {
        处理节点;
        dfs(图,选择的节点); // 递归
        回溯,撤销处理结果
    }
}

 练习

1.三角形路径和最大搜索

 (一)前序DFS(从上至下搜索,实际是暴力解法,测试超时)

#include<iostream>
#include<vector>
using namespace std;
 
void output(vector<vector<int>>& input){
    for(int i=0; i<input.size(); i++){
        for(auto it=input[i].begin(); it!= input[i].end(); it++){
            cout<<*it<<" ";
        }
        cout<<endl;
    }
}
 
struct TreeNode{
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode() : val(0), left(nullptr), right(nullptr) {}
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
    TreeNode(int x, TreeNode* left, TreeNode* right) : val(x), left(left), right(right) {}
};
 
class solution
{
private:
    int maxSum;
    // 前序深度遍历
    void traversal(vector<vector<int>>& tree, int depth, int width, int sum){
        //
        if(depth >= tree.size()){
            if(sum > maxSum) maxSum = sum;
            return;
        }
        // mid
        sum += tree[depth][width];
        // left
        traversal(tree, depth+1, width, sum);
        // right
        traversal(tree, depth+1, width+1, sum);
    }
public:
    int getMaxPathSum(vector<vector<int>>& input_tree){
        maxSum = -1;
        traversal(input_tree, 0, 0, 0);
        return maxSum;
    }
};
 
int main()
{
    // input;
    int num;
    cin>>num;
    while(num--){
        vector<vector<int>> input_tree;
        int depth;
        cin>>depth;
        for(int i=1; i<=depth; i++){
            vector<int> tmp;
            int input;
            for(int j=0; j<i; j++){
                cin>>input;
                tmp.push_back(input);
            }
            input_tree.push_back(tmp);
        }
         
        // // debug_input
        // output(input_tree);
         
        solution mySolve;
        int res = mySolve.getMaxPathSum(input_tree);
        cout<<res<<endl;
    }
    return 0;
}

(二)后序DFS(自底向上搜索,设置memory数组记录各节点子树的最大路径和,相同子树剪枝优化,AC)

(1)递归无返回值

#include<iostream>
#include<vector>
using namespace std;
 
 
void debug_input(vector<vector<int>>& input){
    for(int i=0; i<input.size(); i++){
        for(auto it=input[i].begin(); it!=input[i].end(); it++){
            cout<<*it<<" ";
        }
        cout<<endl;
    }
}
 
class solution
{
private:
    vector<vector<int>> memory;// 记录每个子树maxSum
    // 从下至上遍历->后序->相同子树剪枝
    void traversal(vector<vector<int>>& input, int depth, int width){
        // 终止条件->遇叶节点
        if(depth == input.size()-1){
            memory[depth][width] = input[depth][width];
            return;
        }
        // 遇相同子树->剪枝
        if(memory[depth][width]) return;
         
        // 后序遍历
        // left
        traversal(input, depth+1, width);
        // right
        traversal(input, depth+1, width+1);
        // mid
        memory[depth][width] = input[depth][width] + max(memory[depth+1][width], memory[depth+1][width+1]);
    }
public:
    int getMaxPathSum(vector<vector<int>>& input){
        vector<int> vec(input.size(), 0);
        memory.resize(input.size(), vec);
        traversal(input, 0, 0);
        return memory[0][0];
    }
};
 
int main()
{
    int num;
    cin>>num;
    while(num--){
        vector<vector<int>> input;
        int depth;
        cin>>depth;
        for(int i=1; i<=depth; i++){
            vector<int> tmp;
            for(int j=0; j<i; j++){
                int in;
                cin>>in;
                tmp.push_back(in);
            }
            input.push_back(tmp);
        }
        // debug_input(input);
         
        solution my_solve;
        int res = my_solve.getMaxPathSum(input);
        cout<<res<<endl;
    }
    return 0;
}

(2)递归有返回值

#include<iostream>
#include<vector>
using namespace std;
 
 
void debug_input(vector<vector<int>>& input){
    for(int i=0; i<input.size(); i++){
        for(auto it=input[i].begin(); it!=input[i].end(); it++){
            cout<<*it<<" ";
        }
        cout<<endl;
    }
}
 
class solution
{
private:
    vector<vector<int>> memory;// 记录每个子树maxSum
    // 从下至上遍历->后序->相同子树剪枝
    int traversal(vector<vector<int>>& input, int depth, int width){
        // 终止条件->遇叶节点
        if(depth >= input.size()-1){
            return input[depth][width];
        }
        // 遇相同子树->剪枝
        if(memory[depth][width]) return memory[depth][width];
         
        // 后序遍历
        // left
        int left_sum = traversal(input, depth+1, width);
        // right
        int right_sum = traversal(input, depth+1, width+1);
        // mid
        memory[depth][width] = input[depth][width] + max(left_sum, right_sum);
        return memory[depth][width];
    }
public:
    int getMaxPathSum(vector<vector<int>>& input){
        vector<int> vec(input.size(), 0);
        memory.resize(input.size(), vec);
        int res = traversal(input, 0, 0);
        return res;
    }
};
 
int main()
{
    int num;
    cin>>num;
    while(num--){
        vector<vector<int>> input;
        int depth;
        cin>>depth;
        for(int i=1; i<=depth; i++){
            vector<int> tmp;
            for(int j=0; j<i; j++){
                int in;
                cin>>in;
                tmp.push_back(in);
            }
            input.push_back(tmp);
        }
        // debug_input(input);
         
        solution my_solve;
        int res = my_solve.getMaxPathSum(input);
        cout<<res<<endl;
    }
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1439311.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

pycharm像jupyter一样在控制台查看后台变量

更新下&#xff1a;这个一劳永逸不用一个一个改 https://blog.csdn.net/Onlyone_1314/article/details/109347481 右上角运行

【misc】ctfshow--CTF的一生如履薄冰

解压的附件如下&#xff1a; 666.zip这个压缩包是要密码的&#xff0c;打开txt看一下 这个应该spam encode了 直接解密&#xff1a;spammimic - decode 解密结果为&#xff1a;hppy_n3w_y3ar_every_ctf3r_2024_g0g0g0!!!这个就是压缩包的密码&#xff0c;解压 又是一个加密的…

Centos8保姆级安装教程

1.下载地址 Downloadhttps://www.centos.org/download/ 2.安装教程 第一步创建新的虚拟机 第二步自定义高级 第三步这里是选择系统的兼容性&#xff0c;默认就可以 之后直接下一步 第四步选择稍后安装操作系统 之后点击下一步 第五步选择操作系统Linux 安装的是centos8 64位…

WordPress如何自建txt文本经典语录并随机显示一句话经典语录?

前面跟大家分享的『WordPress集成一言&#xff08;Hitokoto&#xff09;API经典语句功能』一文中就提供有自创API&#xff0c;其中懿古今顶部左上角显示的经典语录用的就是自建一个txt文本文件&#xff0c;然后再在前端网页指定位置随机显示语录。具体操作方法如下&#xff1a;…

网神 SecGate 3600 防火墙 route_ispinfo_import_save 文件上传漏洞复现

0x01 产品简介 网神SecGate 3600防火墙是基于状态检测包过滤和应用级代理的复合型硬件防火墙,是专门面向大中型企业、政府、军队、高校等用户开发的新一代专业防火墙设备,支持外部攻击防范、内网安全、网络访问权限控制、网络流量监控和带宽管理、动态路由、网页内容过滤、邮…

踩坑实录(Third Day)

临近年关&#xff0c;同事们该回家的也都回家了&#xff0c;所以我对工作的欲望不是很强烈&#xff0c;所以就主要是自己学习了一下&#xff0c;在 B 站看看视频&#xff0c;自己敲代码&#xff0c;所以今天没遇到什么坑&#xff0c;但是可以分享一下之前踩到的两个坑。 此为第…

PCIE Order Set

1 Training Sequence Training Sequence是由Order Set(OS) 组成&#xff0c;它们主要是用于bit aligment&#xff0c;symbol aligment&#xff0c;交换物理层的参数。当data_rate 2.5GT or 5GT 它们不会被扰码(scramble)&#xff0c;当date_rate 8GT or higher 根据特殊的规…

Rust开发WASM,WASM Runtime运行

安装wasm runtime curl https://wasmtime.dev/install.sh -sSf | bash 查看wasmtime的安装路径 安装target rustup target add wasm32-wasi 创建测试工程 cargo new wasm_wasi_demo 编译工程 cargo build --target wasm32-wasi 运行 wasmtime ./target/wasm32-wasi/d…

3060ti显卡+cuda12.1+win10编译安装生成fastdeploy的c++与python库

在cuda12中,调用官方发布的fastdeploy会出现报错,故此自行编译fastdeploy库。 官网编译教程:https://github.com/PaddlePaddle/FastDeploy/blob/develop/docs/cn/build_and_install/gpu.md 可选编译选项 编译选项 无论是在何平台编译,编译时仅根据需求修改如下选项,勿…

C语言笔试题之实现C库函数 strstr()(设置标志位)

实例要求&#xff1a; 1、请你实现C库函数strstr()&#xff08;stdio.h & string.h&#xff09;&#xff0c;请在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标&#xff08;下标从 0 开始&#xff09;&#xff1b;2、函数声明&#xff1a;int strStr(char* h…

使用maven命令安装Oracle的jar包到本地仓库

mvn install:install-file -DgroupIdcom.oracle -DartifactIdojdbc6 -Dversion11.2.0.4 -Dpackagingjar -DfileD:\ojdbc6-11.2.0.4.jar ojdbc6-11.2.0.4.jar 下载 链接&#xff1a;https://pan.baidu.com/s/1SqO3Ug7KF8kGr9-jOy3MJQ 提取码&#xff1a;36p9

【GAMES101】Lecture 18 高级外观建模

外观就是材质&#xff0c;就是BRDF&#xff0c;然后对于不同的模型&#xff0c;这个材质的计算不太一样 目录 非表面模型 参与介质 头发 皮毛-动物毛发 颗粒材质&#xff08;Granular material&#xff09; 表面模型 半透明材质&#xff08;Translucent material&#…

17:定时器编程实战

1、实验目的 (1)使用定时器来完成LED闪烁 (2)原来实现闪烁时中间的延迟是用delay函数实现的&#xff0c;在delay的过程中CPU要一直耗在这里不能去做别的事情。这是之前的缺点 (3)本节用定时器来定一个时间&#xff08;譬如0.3s&#xff09;&#xff0c;在这个定时器定时时间内…

相机图像质量研究(8)常见问题总结:光学结构对成像的影响--工厂调焦

系列文章目录 相机图像质量研究(1)Camera成像流程介绍 相机图像质量研究(2)ISP专用平台调优介绍 相机图像质量研究(3)图像质量测试介绍 相机图像质量研究(4)常见问题总结&#xff1a;光学结构对成像的影响--焦距 相机图像质量研究(5)常见问题总结&#xff1a;光学结构对成…

【DIY】断电报警电路,电源监控装置

这个微小的断电报警电路是一种电源监控装置&#xff0c;将掀起的压电扬声器当交流电网电源切断。这表明一些功率的关键仪器如安装在医院照料装置供电损失很有帮助。报警激活在正确的时间是有用信号有停电&#xff0c;应采取紧急行动提供了另一种供电恢复的情况。 这是一个9V电…

【开源】基于JAVA+Vue+SpringBoot的停车场收费系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 停车位模块2.2 车辆模块2.3 停车收费模块2.4 IC卡模块2.5 IC卡挂失模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 停车场表3.2.2 车辆表3.2.3 停车收费表3.2.4 IC 卡表3.2.5 IC 卡挂失表 四、系统实现五、核心代码…

【http】2、http request header Origin 属性、跨域 CORS、同源、nginx 反向代理、预检请求

文章目录 一、Origin 含义二、跨源资源共享&#xff1a;**Cross-Origin Resource Sharing** CORS2.1 跨域的定义2.2 功能概述2.3 场景示例2.3.1 简单请求2.3.2 Preflighted requests&#xff1a;预检请求 2.4 header2.4.1 http request header2.4.1.1 Origin2.4.1.2 Access-Con…

上海泗博HART转ModbusTCP网关HME-635应用案例之组态王和超声波液位计通信

如今工业现场的应用也逐渐把现场的不同应用协议转换成以太网&#xff0c;以此来提升现场的通信速度和质量。Modbus TCP是工业以太网协议的一种&#xff0c;也是现场应用中最常使用的。本应用案例是基于Modbus TCP的组态王和基于HART的超声波液位计之间数据通讯的具体应用。 应用…

ruoyi-nbcio中xxl-job的安装与使用

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a; http://122.227.135.243:9666 更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码&#xff1a; https://gitee.com/nbach…

u8 bit0 :1; “:”位字段的声明(也称为位段)

在C语言中&#xff0c;冒号&#xff08;:&#xff09;用于声明bit字段&#xff0c;也称为位域(Bit-field)。位域允许我们在结构体中对结构成员进行位级的精确操作&#xff0c;主要用于对寄存器和硬件操作进行描述和访问。冒号后面的数字表示该位域的位宽度。 在通信中&#xff…