dp入门:从暴力dfs 到 dp

本篇为小金鱼大佬视频的学习笔记,原视频链接:https://www.bilibili.com/video/BV1r84y1379W?vd_source=726e10ea5b787a300ceada715f64b4bf

基础概念

  暴力dfs很多时候仅能过部分测试点,要想将其优化,一般以 dfs -> 记忆化搜索 -> dp 为路线,后续熟悉后可以直接写出dp代码。

  •    记忆化搜索:在dfs的基础上,增加一个数组用于记录已经被计算过的值,以减少后续的计算来达到优化效果
  •   dp:给定一个问题,将其拆分为无数个可解决的子问题,并将子问题的答案记录下来,根据子问题反推出源问题

  所谓递归,“递”是从上往下,将问题分解为子问题的过程,“归”是从下向上回溯,将已有答案的子问题合并产生答案的过程,而dp就是只调用“归”,从下向上直接找答案

 例题:

本篇以数字三角形为例,分析dfs逐步优化到dp的过程,原题链接:P1216 [USACO1.5] [IOI1994]数字三角形 Number Triangles - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

本题目标是要找到从顶部到底部产生的最大权值。

方法一:暴力递归

  由题可知,一个数字只可以走到他下面的两个数,而在数组中该数下标(x,y),则它可以遍历的数字下标为(x + 1,y)和(x + 1,y + 1),要找到最大的权值,因此递归条件为 max(dfs(x + 1, y), dfs(x + 1, y + 1)) + mp[x][y];

  其实以前刚开始学递归时,一直理解不了return后面这个式子,现在从数学公式来理解的话还是有点不明白,但是可以 通过递归搜索树来理解 

#include<iostream>
using namespace std;

int n;
const int  N = 1010;
int mp[N][N];
int mem[N][N] = { 0 };

int dfs(int x, int y) {
	if (x > n || y > n) return 0;
	return max(dfs(x + 1, y), dfs(x + 1, y + 1)) + mp[x][y];
}
//从顶部到底部产生最大权值
int main() {
	cin >> n;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j <= i; j++) {
			cin >> mp[i][j];
		}
	}
    cout << dfs(0,0);
	return 0;
}

在洛谷上dfs无法通过所有案例,显示tle

方法二:记忆化搜索

  在dfs的基础上,加上一个mem数组用于存储已经计算过的值,可以大大减少计算量

#include<iostream>
using namespace std;

int n;
const int  N = 1010;
int mp[N][N];
int mem[N][N] = { 0 };

int dfs(int x, int y) {
	if (mem[x][y]) return mem[x][y];
	int res = 0;
	if (x > n || y > n) res = 0;
	else res = max(dfs(x + 1, y), dfs(x + 1, y + 1)) + mp[x][y];

	mem[x][y] = res;
	return res;

}

int main() {
	cin >> n;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j <= i; j++) {
			cin >> mp[i][j];
		}
	}

	cout << dfs(0,0);

	return 0;
}

也就是说, 记忆化搜索 = dfs + 记录答案 

同时要注意:

  • 要想实现 记忆化搜索  dfs参数要尽可能少 ,不应该把没影响边界的参数放进来
  • 要想 剪枝 ,就应尽可能把能剪枝的参数写上来

方法三:递推

  递推,也就是从已知答案的小问题逐步推演到源问题的过程,也就是从递归搜索树的下面走到上面回溯的过程,而此过程往往用数组来存储值 。(本题为了便于区分不同方法,用f数组来存储)

  注意: for循环一定注意是从0增还是从n减 ,而这取决于递归搜索树的底部是n还是0。

#include<iostream>
using namespace std;

int n;
const int  N = 1010;
int mp[N][N];
int f[N][N] = { 0 };

//从顶部到底部产生最大权值
int main() {
	cin >> n;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j <= i; j++) {
			cin >> mp[i][j];
		}
	}

	for (int i = n - 1; i >= 0; i--) {
		for (int j = 0; j < n; j++) {
			f[i][j] = max(f[i + 1][j], f[i + 1][j + 1]) + mp[i][j];
		}
	}

	cout << f[0][0];

	return 0;
}

也可以看出:

  •   递推公式 = dfs向下递归公式  
  •   递推数组初始值 = dfs递归边界  

以上是本文全部内容,如果对你有帮助点个赞再走吧~  ₍˄·͈༝·͈˄*₎◞ ̑̑

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

汽车IVI中控开发入门及进阶(十三):语音识别

前言: IVI中控上的语音识别,在目前市场上也是非常显眼的一个创新,大幅改变了传统IVI的操作习惯。 语音识别Speech recognition,也称为自动语音识别(ASR)、计算机语音识别或语音到文本,是一种使程序能够将人类语音处理成书面格式的能力。 语音识别Speech recognition是计…

1.6w字数据库基础知识超详细解析~‍(进阶/复习版)

文章目录 前言一、数据库的操作1.登入数据库2.创建数据库3.显示当前数据库4.使用数据库5.删除数据库 二、常用数据类型三、数据库的约束1约束类型2NULL约束3UNIQUE:唯一约束4DEFAULT&#xff1a;默认值约束5 PRIMARY KEY&#xff1a;主键约束6 FOREIGN KEY&#xff1a;外键约束…

Calendar类 --java学习笔记

Calendar 代表的是系统此刻时间对应的日历通过它可以单独获取、修改时间中的年、月、日、时、分、秒等 常见方法&#xff1a; 创建Calendar对象&#xff1a; 用Calendar.getInStance&#xff08;&#xff09;方法&#xff0c;返回一个此时此刻的日历&#xff08;Calendar&am…

关于IP地址证书的申请

对于直接通过IP地址访问的服务器&#xff0c;为其配置SSL证书同样至关重要。以下是一份详尽的指南&#xff0c;教你如何为你的IP地址申请SSL证书。 IP地址证书目前有DV验证和OV验证两种主流的验证方式&#xff0c;DV验证只需验证IP的所有权&#xff0c;OV的在此基础上&#xff…

换根dp,LeetCode310. 最小高度树

一、题目 1、题目描述 树是一个无向图&#xff0c;其中任何两个顶点只通过一条路径连接。 换句话说&#xff0c;一个任何没有简单环路的连通图都是一棵树。 给你一棵包含 n 个节点的树&#xff0c;标记为 0 到 n - 1 。给定数字 n 和一个有 n - 1 条无向边的 edges 列表&#…

自媒体人的超级宝典

这个10块钱的小报童还有谁没买&#xff1f; 你可别等到它涨到19.9的时候来问我有没有优惠 昨天正式发售就已经2300人了&#xff0c;之前可是几个小时就涨了400多人&#xff0c;照这个速度下去&#xff0c;明天就要涨价了。 说实话&#xff0c;我看了里面的内容&#xff0c;觉…

Linux网络编程: 以太网帧Frame/ARP/RARP详解

一、TCP/IP五层模型 物理层&#xff08;Physical Layer&#xff09;&#xff1a;物理层是最底层&#xff0c;负责传输比特流&#xff08;bitstream&#xff09;以及物理介质的传输方式。它定义了如何在物理媒介上传输原始的比特流&#xff0c;例如通过电缆、光纤或无线传输等。…

SAP Activate项目管理方法论路线图

SAP Activate 是 SAP 推出的一种基于敏捷方法论的灵活、快速且引导式的实施方法论&#xff0c;专为加速SAP S/4HANA和其他SAP解决方案的部署而设计。这个方法论结合了最佳实践、引导配置和方法论本身的强大能力&#xff0c;以确保项目的快速实施和成功部署。SAP Activate的核心…

ffmpeg 滤镜实现不同采样率多音频混音

音频混音在音视频开发中是十分重要的一个环节,所谓音频混音就是将所有需要混音的数据相加得到混音数据,然后通过某个算法进行非法数据的处理;例如相加数值超过最大值,最小值等! 在实际的音频开发中,要实现混音的流程如下: 因此我们的编码实现就分为五部分:寻找…

22-分支和循环语句_while语句(下)(初阶)

该代码输出什么&#xff1f; int main() {char ch \0;while ((ch getchar()) ! EOF){if (ch < 0 || ch>9){continue;}putchar(ch);}return 0; } 结果&#xff1a;该代码只打印数字字符 附&#xff1a;ASCII码表

Python基础入门 --- 5.函数

文章目录 Python基础入门5.函数5.1 基本定义5.2 传入参数5.3 返回值5.3.1 None类型 5.4 说明文档5.5 嵌套调用 Python基础入门 5.函数 定义&#xff1a;可重复使用&#xff0c;用来实现特定功能的代码段。 # 不使用内置函数len&#xff0c;统计字符串的长度 str "Hell…

南卡罗来纳州历史和文化经济地理和自然政治和社会教育1. 加州大学公布2024年秋季入学新生和转学申请数据2. 2024考研国家线公布路德会信徒核心信仰礼拜和

目录 南卡罗来纳州 历史和文化 经济 地理和自然 政治和社会 教育 1. 加州大学公布2024年秋季入学新生和转学申请数据 2. 2024考研国家线公布 路德会信徒 核心信仰 礼拜和实践 分布 社会和文化影响 约翰塞巴斯蒂安巴赫 生平简介 音乐风格和作品 遗产和影响 …

AXI Lite协议详解

AXI Lite协议详解 axi&#xff08;Advanced eXtensible Interface&#xff09;是一种总线协议&#xff0c;该协议是ARM公司提出的amba&#xff08;Advanced Microcontroller Bus Architecture&#xff09;3.0协议中最重要的部分&#xff0c;是一种面向高性能、高带宽、低延迟的…

C++17之std::variant

1. std::variant操作 如下列出了为std:: variable <>提供的所有操作。

Docker 学习笔记一

一、什么是docker Docker 是一个基于轻量级虚拟化技术的容器&#xff0c;整个项目基于Go语言开发&#xff1b;Docker是一个C/S架构&#xff0c;后端众多模块各司其职&#xff0c;docker的daemon是运行在主机上通过client可以进行通信。 docker 由三部分组成&#xff1a;镜像(…

Rust 构建开源 Pingora 框架可以与nginx媲美

一、概述 Cloudflare 为何弃用 Nginx&#xff0c;选择使用 Rust 重新构建新的代理 Pingora 框架。Cloudflare 成立于2010年&#xff0c;是一家领先的云服务提供商&#xff0c;专注于内容分发网络&#xff08;CDN&#xff09;和分布式域名解析。它提供一系列安全和性能优化服务…

Figure 01掀起了具身智能的崭新篇章

在人工智能的发展历程中&#xff0c;OpenAI始终扮演着创新的先锋角色。最近&#xff0c;他们与Figure公司的合作成果尤为引人注目&#xff0c;这一合作将多模态大模型技术成功应用于Figure 01机器人的开发中&#xff0c;为人类与机器的互动开辟了全新的时代。该机器人不仅能够与…

innovus中path group 的策略和应用(上)

在所有的后端工具里边&#xff0c;有三个重要的引擎&#xff1a;auto-place&#xff0c;CTS&#xff0c;auto-route三个。这里边的auto-place是决断了整个设计时序的基点。由于&#xff0c;auto-place的动作是在设计的preCTS阶段&#xff0c;所以这里的设计时序就是广义上说的&…

HDFSDATANODE数据传输详解

本文主要阐述datanode中一个socket连接接收字节流的构成&#xff0c;帮助datanode的接收与处理数据。注意hadoop版本为3.1.1。 写在前面 Datanode本质上也是TCPServer&#xff0c;一般的TCPServer接到客户端请求以后会分配一个线程处理&#xff0c;对于Datanode而言&#xff…

npm、nodejs和vue之间关系和区别介绍

本文讲解npm、Node.js和Vue.js这三者之间的关系和区别&#xff0c;以及它们各自的特点。 首先&#xff0c;让我们来了解一下Node.js。 **Node.js** 是一个开源的服务器端运行环境&#xff0c;它允许开发者使用JavaScript来编写服务器端的代码。在传统的Web开发中&#…