【算法笔记】深入理解dfs(两道dp题)

news2024/10/1 23:30:47

DFS过程的概述

一个一个节点的搜,如果是树状结构的话,先找到最左边那一条分支搜到最后一个节点,这个时候最后一个节点(假设是b)的数据会被更新(具体看题目的要求),然后返回到上一个节点(假设是a)(如果有两层dfs的话,需要画个分叉图辅助理解)。 此时a节点使用下层刚刚被更新过的数据(即b节点)来更新a节点的数据。更新完后如果a节点下方还有一个节点,那么就要继续往下搜索,继续把a节点的数据更新完全(也就是把a节点的分支都找完了)。那么当a节点的数据被完全更新完后,又会重复上面那个过程。也就是说我们可以把以a节点为根的子树看成一个新的节点(这样子方便理解)

从上面的分析可以看出,dfs会把更新后的数据存储起来,不管这个更新是完全更新还是部分更新。这个也很好理解,因为一次dfs只会对一个节点进行操作(而且是从下往上的过程)(这就说明一个节点可能要经过多次dfs才能把数据完全更新),也就是用一种很笨的方法(如果没有剪枝的话,和暴搜没区别)去更新数据和答案。

有依赖的背包问题

思路:在这一题里,我们需要更新每颗子树的最大价值,然后计算出包括根节点的树的最大价值。对于树的遍历,我们一般可以用dfs来遍历,因为dfs从最底层的节点开始往上遍历。

这里的f[ i ][ j ]的含义是考虑第i个物品为根节点的子树,且选上i,体积不超过j的最大价值。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>

using namespace std;
const int N = 110;
vector<int> g[N];
int v[N], w[N];
int f[N][N];
int n, m;

void dfs(int u)
{
    for(int i = v[u]; i <= m; i ++) f[u][i] = w[u];
    for(int i = 0; i < g[u].size(); i ++)
    {
        int y = g[u][i];
        dfs(y); //一直往下搜索树的节点,直到找到最底层的节点,然后执行状态转移方程,然后返回到上一个节点
        for(int j = m; j >= v[u]; j --)
            for(int k = 0; k <= j - v[u]; k ++)
            {
                f[u][j] = max(f[u][j], f[y][k] + f[u][j-k]);
            }
    }
}

int main()
{   
    int root;
    cin>>n>>m;
    for(int i = 1; i <= n; i ++)
    {
        int fa;
        cin>>v[i]>>w[i]>>fa;
        if(fa == -1) root = i;
        else 
            g[fa].push_back(i);
    }
    
    dfs(root);
    cout<<f[root][m];
}

导弹防御系统(线性dp)

思路:这一题好像没有什么好的办法,只能用dfs加剪枝,如果不剪枝的话肯定会TLE的,因为每个点有两种情况可选:加入到上升子序列或加入到下降子序列。那么综合以上来看的话,时间复杂度回到一个 n * 2 ^ n。

用两次dfs来搜索所有情况的组合。

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;
const int N = 55;
int h[N];
int up[N], down[N];
int ans, n;

void dfs(int u, int su, int sd)
{
    if(su + sd >= ans) return; //剪枝,如果此时上升和下降序列的方案数大于等于ans那么直接返回
    
    if( u == n)
    {
        ans = min(ans, su + sd); //更新答案
        return;
    }

    //上升序列方案统计
    int k = 0;
    while( k < su && up[k] >= h[u]) k++;
    if( k < su)
    {
        int t = up[k];
        up[k] = h[u];
        dfs(u+1, su, sd);
        up[k] = t;
    }
    else
    {
        up[k] = h[u];
        dfs(u+1, su+1, sd);
    }
    
    //下降序列方案统计
    k = 0;
    while( k < sd && down[k] <= h[u]) k ++;
    if( k < sd)
    {
        int t = down[k];
        down[k] = h[u];
        dfs(u+1, su, sd);
        down[k] = t;
    }
    
    else
    {
        down[k] = h[u];
        dfs(u+1, su, sd+1);
    }

}

int main()
{
    while(cin>>n, n)
    {
        for(int i = 0; i < n; i ++) cin>>h[i];
        ans = n;    
        dfs(0, 0, 0);
        cout<<ans<<endl;
    }
}

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

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

相关文章

debug mccl 02 —— 环境搭建及初步调试

1, 搭建nccl 调试环境 下载 nccl 源代码 git clone --recursive https://github.com/NVIDIA/nccl.git 只debug host代码&#xff0c;故将设备代码的编译标志改成 -O3 (base) hipperhipper-G21:~/let_debug_nccl/nccl$ git diff diff --git a/makefiles/common.mk b/makefiles/…

TypeScript接口、对象

目录 1、TypeScript 接口 1.1、实例 1.2、联合类型和接口 1.3、接口和数组 1.4、接口和继承 1.5、单继承实例 1.6、多继承实例 2、TypeScript 对象 2.2、对象实例 2.3、TypeScript类型模板 2.4、鸭子类型&#xff08;Duck typing&#xff09; 1、TypeScript 接口 接口…

rust sqlx包(数据库相关)使用方法+问题解决

可以操作pgsql、mysql、mssql、sqlite 异步的&#xff0c;性能应该不错&#xff0c;具体使用有几个坑 除了sqlx库&#xff0c;还有对于具体数据库的库&#xff0c;比如postgres库 演示以pgsql为例&#xff0c;更新时间2024.1.6 官方github: sqlx github rust官方文档&#xff1…

C++ Qt开发:Charts与数据库组件联动

Qt 是一个跨平台C图形界面开发库&#xff0c;利用Qt可以快速开发跨平台窗体应用程序&#xff0c;在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置&#xff0c;实现图形化开发极大的方便了开发效率&#xff0c;本章将重点介绍Charts组件与QSql数据库组件的常用方法及灵活…

【深度学习】cv领域中各种loss损失介绍

文章目录 前言一、均方误差二、交叉熵损失三、二元交叉熵损失四、Smooth L1 Loss五、IOU系列的loss 前言 损失函数是度量模型的预测输出与真实标签之间的差异或误差&#xff0c;在深度学习算法中起着重要作用。具体作用&#xff1a; 1、目标优化&#xff1a;损失函数是优化算法…

Unable to connect to Redis server

报错内容&#xff1a; Exception in thread "main" org.redisson.client.RedisConnectionException: java.util.concurrent.ExecutionException: org.redisson.client.RedisConnectionException: Unable to connect to Redis server: 175.24.186.230/175.24.186.230…

C语言scanf()函数详解

目录 1. scanf&#xff08;&#xff09;函数简介 1.1 函数原型 1.2 头文件 1.3 返回值 1.4 参数 2.格式说明符 3.输入格式控制 关于‘ * ’的例子 关于width域宽的例子 关于length长度修饰符的说明 4. 其他常见问题说明 4.1 scanf&#xff08;&#xff09;函数连…

2024年【烟花爆竹经营单位主要负责人】考试题及烟花爆竹经营单位主要负责人考试资料

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年【烟花爆竹经营单位主要负责人】考试题及烟花爆竹经营单位主要负责人考试资料&#xff0c;包含烟花爆竹经营单位主要负责人考试题答案和解析及烟花爆竹经营单位主要负责人考试资料练习。安全生产模拟考试一点通…

纹理贴图如何为游戏角色增添质感

在线工具推荐&#xff1a; 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 游戏角色的3D建模是位移贴图技术广泛应用的领域之一。通过位移贴图&a…

记录汇川:H5U与Fctory IO 测试1

主程序&#xff1a; 子程序&#xff1a; Fctory IO通讯配置如下 &#xff1a; H5U作服务器&#xff0c;Fctory IO作客户端 这里参考&#xff1a;HU5作服务器地址 实现的动作如下&#xff1a; H5U与Factory IO联动

华为MDC610接口说明

1、MDC610对外功能接口 2、1、MDC610硬件技术规格

数据库初始化脚本(用 truncate 命令一键清空某个数据库中全部数据表数据)

数据库初始化脚本&#xff08;用 truncate 命令一键清空某个数据库中全部数据表数据&#xff09; 1.执行下面的sql语句生成“清空数据库的sql脚本”2.执行“清空数据库的sql脚本” 在开发中&#xff0c;当数据表结构有变动或者数据库中有脏数据时&#xff0c;想要清空数据表中的…

Python中的@abstractmethod

abstractmethod 是 Python 中 abc 模块&#xff08;Abstract Base Classes&#xff09;提供的一个装饰器&#xff0c;用于声明抽象方法。抽象方法是指在抽象类中声明但没有提供具体实现的方法&#xff0c;而是由其子类提供具体实现。 使用 abstractmethod 装饰器可以使得子类在…

普通BUG

IDEA包折叠 如果自动紧凑包名,则有些时候创建新包或类的时候不能达到想要的摆放层级关系,此时右上角搜索按钮搜hide middle,关掉紧凑即可,然后既可以每层一个包不折叠. 效果: 20240105println输出多个参数 int a 10;int b 20;报错println是可以输出多个参数的,但不支持直接用…

C++中的new和delete

相关文章 C智能指针 文章目录 相关文章前言一、new 运算符1. operator new 函数的范围2. 在类中重载new运算符3. 分配失败 二、delete 运算符1. 内存泄露统计示例2. 在类中重载delete运算符 总结 前言 在C中&#xff0c;new和delete是用于动态内存管理的运算符&#xff0c;它们…

优势演员-评论家算法 A2C

优势演员-评论家算法 A2C 优势演员-评论家算法 A2C主要思想目标函数 优势演员-评论家算法 A2C 前置知识&#xff1a;演员-评论家算法&#xff1a;多智能体强化学习核心框架 主要思想 AC 网络结构&#xff1a; 策略网络 - 演员: 这个网络负责根据当前的状态选择动作。它输出的是…

更改ERPNEXT源

更改ERPNEXT源 一&#xff0c; 更改源 针对已经安装了erpnext的&#xff0c;需要更改源的情况&#xff1a; 1, 更改为官方默认源, 进入frapp-bench的目录&#xff0c; 然后执行: bench remote-reset-url frappe //重设frappe的源为官方github地址。 bench remote-reset-url…

如何使用免费的ZeroSSL证书保护您的网站

使用 ZeroSSL 在您的站点上轻松实施 SSL。我们的指南涵盖了免费证书设置&#xff0c;确保安全和加密的用户连接。 如今&#xff0c;保护您的网站不仅是一种建议&#xff0c;而且是一种必需品。这就是SSL证书发挥作用的地方。它们对用户浏览器和网站之间传输的数据进行加密&…

复旦MBA科创青干营(二期):探索合肥科创企业的创新之路

11月18日-19日&#xff0c;复旦MBA科创青干营二期学生开启了整合实践活动的第三次企业参访&#xff0c;前往位于合肥的蔚来第二先进制造基地、安徽万邦医药科技股份有限公司和合肥国轩高科动力能源有限公司&#xff0c;在学术导师和科创企业家“双导师”的指导下&#xff0c;深…

LeetCode 每日一题 Day 3334(hard)35 ||二进制枚举/单调栈/链表遍历

2397. 被列覆盖的最多行数 给你一个下标从 0 开始、大小为 m x n 的二进制矩阵 matrix &#xff1b;另给你一个整数 numSelect&#xff0c;表示你必须从 matrix 中选择的 不同 列的数量。 如果一行中所有的 1 都被你选中的列所覆盖&#xff0c;则认为这一行被 覆盖 了。 形式…