深入理解动态规划(dp)--(提前要对dfs有了解)

前言:对于动态规划:该算法思维是在dfs基础上演化发展来的,所以我不想讲的是看到一个题怎样直接用动态规划来解决,而是说先用dfs搜索,一步步优化,这个过程叫做动态规划。(该文章教你怎样一步步的解决这类题)

目录

一、动态规划入门

二、跳台阶问题---来自AcWing 

1.用暴力搜索dfs来解

2.记忆化搜索实现

3.递推实现

二、大盗阿福---来自AcWing

1.用dfs暴力搜索

2.记忆化搜索

3.递推实现

四、数字三角形---来自洛谷

1.用暴力搜索dfs

2.用记忆化搜索

3.递推dp


一、动态规划入门

动态规划就是:给定一个问题,我们将它拆解为一个个子问题,直到子问题可以直接解决,然后把子问题的答案保存起来,以减少重复计算,再根据子问题答案反推,得出原问题的一种方法

动态规划入门思路:dfs暴力--->记忆化搜索--->递推DP

下面正式开始讲解,还是在题中带大家慢慢理解动态规划的思维

二、跳台阶问题---来自AcWing 

一个楼梯共有n级台阶,每次可以走一级或者两级,问从第0级台阶走到第n级台阶一共有多少种方案。

输入格式:

共一行,包含一个整数n

输出格式:

共一行,包含一个整数,表示方案数

数据范围:

1<=n<=15

输入样例:

5

输出样例:

8

1.用暴力搜索dfs来解

  • 这个题大部分同学都应该见过,最初我们用递归来解决这道题,其实本质上也是dfs暴力搜索
#include<iostream>
#include<algorithm>
using namespace std;
int n;
int fib(int x)
{if (x == 1)return 1;else if (x == 2)return 2;else return fib(x - 1) + fib(x - 2);
}
int main(void)
{cin >> n;int res = fib(n);cout << res << endl;return 0;
}

这时我们会发现,当n=41时,时间就快到了1s,所以要想办法去优化代码

2.记忆化搜索实现

这里我拿n=5为例,来画一下搜索树,然后分析一下怎么优化

 

如果是用一个数组来存储一下的话,直接就省去了这棵大树的右分支,因为左分支中的3已经搜索过了,当以后遇到别的题或者n更大时这棵树的左右分支也会很大,所以省去的搜索也就更多。 

#include<iostream>
#include<algorithm>
using namespace std;
int arr[100];
int n;
int fib(int x)
{if(arr[x])return arr[x];int sum=0;if (x == 1) sum=1;else if (x == 2) sum=2;else sum=fib(x-1)+fib(x-2);arr[x]=sum;return sum;
}
int main(void)
{scanf("%d",&n);int res = fib(n);printf("%d\n",res);return 0;
}

 直接将900多毫秒优化到了2毫秒。

3.递推实现

递归的过程:“归”的过程才是产生答案的过程

                      “递”的过程是分解子问题的过程(把大问题分解为子问题)

“递”:自顶向下

“归”:自底向上

而我们自底向上一步步推出答案的过程-----就是递推

好,接下来就用递推的方式进行编程:

#include<iostream>
#include<algorithm>
using namespace std;
int F[100];
int n;
int main(void)
{scanf("%d",&n);F[1]=1,F[2]=2;for(int i=3;i<=n;i++){F[i]=F[i-2]+F[i-1];//这个递推公式也就是dfs的状态转移公式}printf("%d\n",F[n]);return 0;
}

总结: 

跳台阶这道题:我们就是这样做的:

最暴力的dfs--->记忆化搜索--->递推(dp)

记忆化搜索=暴力bfs+记录答案

递推的公式=dfs向下递归的公式

递推数组的初始值=递归的边界

二、大盗阿福---来自AcWing

阿福是一名经验丰富的大盗。趁着月黑风高,阿福打算今晚洗劫一条街上的店铺。这条街上一共有 N 家店铺,每家店中都有一些现金。阿福事先调查得知,只有当他同时洗劫了两家相邻的店铺时,街上的报警系统才会启动,然后警察就会蜂拥而至。
作为一向谨慎作案的大盗,阿福不愿意冒着被警察追捕的风险行窃。
他想知道,在不惊动警察的情况下,他今晚最多可以得到多少现金?
输入格式:
输入的第一行是一个整数 T,表示一共有 T 组数据。接下来的每组数据,第一行是一个整数 N ,表示一共有 N 家店铺,第二行是 N 个被空格分开的正整数,表示每一家店铺中的现金数量每家店铺中的现金数量均不超过1000。
输出格式:

对于每组数据,输出一行

该行包含一个整数,表示阿福在不惊动警察的情况下可以得到的现金

范围:

1<=T<=50

1<=N<=1e5

输入样例:

2

3

1 8 2

4

10 7 6 14

输出样例:

8

24

1.用dfs暴力搜索

先画搜索树,这道题是选和不选问题

#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1e5 + 10;
int arr[N];
int n, t;
int res = 0;
int dfs(int x)//x表示当前正在考虑哪家店
{if (x > n)return 0;else return max(dfs(x + 1), dfs(x + 2) + arr[x]);
}
int main(void)
{cin >> t;while (t--){cin >> n;for (int i = 1; i <= n; i++)scanf_s("%d", &arr[i]);int res = dfs(1);}return 0;
}

 放到官网提交一下答案发现,时间超时,因为dfs的时间复杂度是2的n次方,超时是理所当然的事,还是要想办法优化

2.记忆化搜索

要想实现记忆化搜索的话,那么dfs的参数就需要尽可能的少,不应该把没有影响到边界的参数放进来

#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1e5 + 10;
int arr[N];
int mem[N];
int n, t;
int res = 0;
int dfs(int x)//x表示当前正在考虑哪家店
{if (mem[x])return mem[x];int sum = 0;if (x > n) sum = 0;else sum = max(dfs(x + 1), dfs(x + 2) + arr[x]);mem[x] = sum;return sum;
}
int main(void)
{cin >> t;while (t--){cin >> n;for (int i = 1; i <= n; i++)scanf_s("%d", &arr[i]);memset(mem, 0, sizeof mem);int res = dfs(1);}return 0;
}

跟跳台阶一样的套路,创建一个数组,存放数据。

3.递推实现

前面也说过了,递推的过程就是递归的“归”,由搜索树的最底层开始向上推,并且递推的公式就是向下递归的公式.

#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1e5 + 10;
int arr[N];
//int mem[N];
int f[N];
int n, t;
int res = 0;
#if 0
int dfs(int x)//x表示当前正在考虑哪家店
{if (mem[x])return mem[x];int sum = 0;if (x > n) sum = 0;else sum = max(dfs(x + 1), dfs(x + 2) + arr[x]);mem[x] = sum;return sum;
}
#endif 
int main(void)
{cin >> t;while (t--){cin >> n;for (int i = 1; i <= n; i++)scanf_s("%d", &arr[i]);//memset(mem, 0, sizeof mem);memset(f, 0, sizeof f);for (int i = n; i >= 0; i--){f[i] = max(f[i + 1], f[i + 2] + arr[i]);}//int res = dfs(1);}return 0;
}

四、数字三角形---来自洛谷

还是一样的套路,三种方法解决问题(我希望大家先自己去尝试用这三种方法动手打一下代码,哪里有不明白的直接看代码再自己理解一下,编程还是自己去上手才能看出来明白还是不明白)

1.用暴力搜索dfs

#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1005;
int arr[N][N];
int n;
int dfs(int x, int y)
{if (x > n || y > n)return 0;else return max(dfs(x + 1, y) + arr[x][y], dfs(x + 1, y + 1) + arr[x][y]);
}
int main(void)
{cin >> n;for (int i = 1; i <= n; i++){for (int j = 1; j <= i; j++){cin >> arr[i][j];}}int res = dfs(1, 1);cout << res << endl;return 0;
}

2.用记忆化搜索

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1005;
int arr[N][N];
int mem[N][N];
int n;
int dfs(int x, int y)
{if(mem[x][y])return mem[x][y];int sum=0;if (x > n || y > n) sum = 0;else sum = max(dfs(x + 1, y) + arr[x][y], dfs(x + 1, y + 1) + arr[x][y]);mem[x][y]=sum;return sum;
}
int main(void)
{cin >> n;for (int i = 1; i <= n; i++){for (int j = 1; j <= i; j++){cin >> arr[i][j];}}memset(mem,0,sizeof mem);int res = dfs(1, 1);cout << res << endl;return 0;
}

3.递推dp

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1005;
int arr[N][N];
int f[N][N];
int n;
int main(void)
{cin >> n;for (int i = 1; i <= n; i++){for (int j = 1; j <= i; j++){cin >> arr[i][j];}}for (int i = n; i >= 1; i--){for (int j = 1; j <= i; j++){f[i][j] = max(f[i + 1][j] + arr[i][j], f[i + 1] [j + 1] + arr[i][j]);}}cout << f[1][1] << endl;return 0;
}

最后:希望读完这篇文章的你,对动态规划有了更深入的了解!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

0基础跟德姆(dom)一起学AI 自然语言处理19-输出部分实现

1 输出部分介绍 输出部分包含: 线性层softmax层 2 线性层的作用 通过对上一步的线性变化得到指定维度的输出, 也就是转换维度的作用. 3 softmax层的作用 使最后一维的向量中的数字缩放到0-1的概率值域内, 并满足他们的和为1. 3.1 线性层和softmax层的代码分析 # 解码器类…

uart iic spi三种总线的用法

1、uart串口通信 这种连接方式抗干扰能力弱&#xff0c;旁边有干扰源就会对收发的电平数据造成干扰&#xff0c;进而导致数据失真 这种连接方式一般适用于一块板子上面的两个芯片之间进行数据传输 &#xff0c;属于异步全双工模式。 1.空闲位&#xff1a;当不进行数据收发时&am…

类与对象(上)

面向过程和面向对象初步认识 C语言是面向过程的&#xff0c;关注的是过程&#xff0c;分析出求解问题的步骤&#xff0c;通过函数调用逐步解决问题。 C是基于面向对象的&#xff0c;关注的是对象&#xff0c;将一件事情拆分成不同的对象&#xff0c;靠对象之间的交互完成。 类的…

三元组抽取在实际应用中如何处理语义模糊性?

在实际应用中&#xff0c;三元组抽取面临语义模糊性的问题&#xff0c;这主要体现在输入文本的非规范描述、复杂句式以及多义性等方面。为了有效处理这种模糊性&#xff0c;研究者们提出了多种方法和技术&#xff0c;以下是一些关键策略&#xff1a; 基于深度学习的方法 深度学…

【线性代数】基础版本的高斯消元法

[精确算法] 高斯消元法求线性方程组 线性方程组 考虑线性方程组&#xff0c; 已知 A ∈ R n , n , b ∈ R n A\in \mathbb{R}^{n,n},b\in \mathbb{R}^n A∈Rn,n,b∈Rn&#xff0c; 求未知 x ∈ R n x\in \mathbb{R}^n x∈Rn A 1 , 1 x 1 A 1 , 2 x 2 ⋯ A 1 , n x n b 1…

智慧脚下生根,智能井盖监测终端引领城市安全新革命

在繁忙的都市生活中&#xff0c;我们往往只关注地面的繁华与喧嚣&#xff0c;却忽略了隐藏在地面之下的基础设施——井盖。这些看似不起眼的井盖&#xff0c;实则承担着排水、通讯、电力等重要功能&#xff0c;是城市安全运转的重要一环。然而&#xff0c;传统的井盖管理面临着…

如何快速开发LabVIEW项目,成为LabVIEW开发的高手

发现了一篇多年前写的文章&#xff0c;转发到这里 如何快速开发LabVIEW项目&#xff0c;成为LabVIEW开发的高手。 如果您手里有LabVIEW项目&#xff0c;领导催的又很紧&#xff0c;该怎么办&#xff1f; 如果您公司规模小&#xff0c;就想把LabVIEW项目快速搞定&#xff0c;有什…

Zemax 非序列模式下的颜色检测器和颜色混合

在 Zemax 的非序列模式中&#xff0c;探测器用于捕获系统中射线的信息。可以使用各种类型的探测器来捕获光学系统性能的不同方面&#xff0c;例如矩形探测器&#xff0c;它存储撞击它的 NSC 源射线的能量数据。 另一种经常使用的探测器类型是 Detector Color&#xff0c;它是一…

Redis(5,jedis和spring)

在前面的学习中&#xff0c;只是学习了各种redis的操作&#xff0c;都是在redis命令行客户端操作的&#xff0c;手动执行的&#xff0c;更多的时候就是使用redis的api&#xff08;&#xff09;&#xff0c;进一步操作redis程序。 在java中实现的redis客户端有很多&#xff0c;…

AAAI2024论文解读|HGPROMPT Bridging Homogeneous and Heterogeneous Graphs

论文标题 HGPROMPT: Bridging Homogeneous and Heterogeneous Graphs for Few-shot Prompt Learning 跨同构异构图的小样本提示学习 论文链接 HGPROMPT: Bridging Homogeneous and Heterogeneous Graphs for Few-shot Prompt Learning论文下载 论文作者 Xingtong Yu, Yuan…

闲鱼自动抓取/筛选/发送系统

可监控闲鱼最新发布商品&#xff0c;发送钉钉 1&#xff0c;精准关键词匹配&#xff1a;输入核心关键词&#xff0c;精准定位与之高度契合的信息&#xff0c;确保搜索结果直击要点&#xff0c;满足您对特定内容的急切需求。 2&#xff0c;标题关键词智能筛选&#xff1a;不仅着…

AI编程工具使用技巧:在Visual Studio Code中高效利用阿里云通义灵码

AI编程工具使用技巧&#xff1a;在Visual Studio Code中高效利用阿里云通义灵码 前言一、通义灵码介绍1.1 通义灵码简介1.2 主要功能1.3 版本选择1.4 支持环境 二、Visual Studio Code介绍1.1 VS Code简介1.2 主要特点 三、安装VsCode3.1下载VsCode3.2.安装VsCode3.3 打开VsCod…

【Unity3D】Unity混淆工具Obfuscator使用

目录 一、导入工具 二、各种混淆形式介绍 2.1 程序集混淆 2.2 命名空间混淆 2.3 类混淆 2.4 函数混淆 2.5 参数混淆 2.6 字段混淆 2.7 属性混淆 2.8 事件混淆 三、安全混淆 四、兼容性处理 4.1 动画方法兼容 4.2 GUI方法兼容 4.3 协程方法兼容 五、选项 5.1 调…

2024年终总结:技术成长与突破之路

文章目录 前言一、技术成长&#xff1a;菜鸟成长之路1. 学习与实践的结合2. 技术分享与社区交流 二、生活与事业的平衡&#xff1a;技术之外的思考1. 时间管理与效率提升2. 技术对生活的积极影响 三、突破与展望&#xff1a;未来之路1. 技术领域的突破2. 未来规划与目标 四、结…

计算机网络-运输层

重点内容&#xff1a; 运输层 是整个网络体系结构中的关键层次之一。一定要弄清以下一些重要概念&#xff1a; (1) 运输层为相互通信的应用进程提供逻辑通信。 (2) 端口和套接字的意义。 (3) 无连接的 UDP 的特点。 (4) 面向连接的 TCP 的特点。 (5) 在不可靠的网…

【Elasticsearch】inference ingest pipeline

Elasticsearch 的 Ingest Pipeline 功能允许你在数据索引之前对其进行预处理。通过使用 Ingest Pipeline&#xff0c;你可以执行各种数据转换和富化操作&#xff0c;包括使用机器学习模型进行推理&#xff08;inference&#xff09;。这在处理词嵌入、情感分析、图像识别等场景…

使用 .NET Core 6.0 Web API 上传单个和多个文件

示例代码&#xff1a; https://download.csdn.net/download/hefeng_aspnet/90138968 介绍 我们将在 IFormFile 接口和 .NET 提供的其他接口的帮助下&#xff0c;逐步讨论单个和多个文件上传。 .NET 提供了一个 IFormFile 接口&#xff0c;代表 HTTP 请求中传输的文件。 此外…

Ceisum无人机巡检直播视频投射

接上次的视频投影&#xff0c;Leader告诉我这个视频投影要用在两个地方&#xff0c;一个是我原先写的轨迹回放那里&#xff0c;另一个在无人机起飞后的地图回显&#xff0c;要实时播放无人机拍摄的视频&#xff0c;还要能转镜头&#xff0c;让我把这个也接一下。 我的天&#x…

Day21-【软考】短文,计算机网络开篇,OSI七层模型有哪些协议?

文章目录 OSI七层模型有哪些&#xff1f;有哪些协议簇&#xff1f;TCP/IP协议簇中的TCP协议三次握手是怎样的&#xff1f;基于UDP的DHCP协议是什么情况&#xff1f;基于UDP的DNS协议是什么情况&#xff1f; OSI七层模型有哪些&#xff1f; 题目会考广播域 有哪些协议簇&#x…

媒体新闻发稿要求有哪些?什么类型的稿件更好通过?

为了保证推送信息的内容质量&#xff0c;大型新闻媒体的审稿要求一向较为严格。尤其在商业推广的过程中&#xff0c;不少企业的宣传稿很难发布在这些大型新闻媒体平台上。 媒体新闻发稿要求有哪些&#xff1f;就让我们来了解下哪几类稿件更容易过审。 一、媒体新闻发稿要求有哪…