小工具知识网

当前位置: 首页 > 行业知识 > ★动态规划(DP算法)详解

行业知识

★动态规划(DP算法)详解

2026-11-11 21:49:52 来源:互联网转载

什么���动态规划:动态规划_百度百科

内容太多了不作介绍,重点部分是无后效性,重叠子问题,最优子结构。

问S->P1和S->P2有多少种路径数,毫无疑问可以先从S开始深搜两次,S->P1和S->P2找出所有路径数,但是当这个图足够大,那就会超时。

动态规划旨在用空间换时间,我们可以发现S->P2的路上,实际上重复计算了S->P1,然后再去计算P1->P2,如果我们第一次计算S->P1的时候,保留了P1点的路径数,那么就不用再次计算S->P1了。

无后效性:未来的状态不会影响过去的状态,如果我在P1->P2的时候,S->P1多了一条路出来,那么先前保留的路径数就是错误的。

tip:下面的例题讲解并不是特别好,还未修正,建议先拉到最下面看20230504 Update.


经典的数塔问题也是dp算法的入门问题之一

假设你有这么一个数塔,你的目标是求最底层到最高层,求出最大路径和

比如3->7->2->9这个路径,他的路径和是3+7+2+9

不难发现如果要求到9的最大路径和,首先要求出他前一层的最大路径

核心代码dp[i][j]=max(dp[i-1][j],dp[i-1][j+1])+a[i][j]

dp[i][j](9的最大路径和)

a[i][j](9自己)

dp[i-1][j](前一层5的最大路径和)dp[i-1][j+1](前一层2的最大路径和)

在前一层的最大路径和取大的那一个


例题:[NOIP2005 普及组] 采药 - 洛谷

这道题输入这么少也不用scanf了,直接上cin加上小优化

inline void scan(){    ios::sync_with_stdio(false);//解除与scanf和cout的同步,具体体现在缓冲区    cin.tie(nullptr),cout.tie(nullptr);//可以加快一点速度    cin>>T>>m;    for(int i=1;i>t[i]>>v[i];}

很明显就是各个最优子问题的问题,要取到最多的价值,必然前一个状态也是最多的。

所以考虑定义问题的全部基础属性,每个草药有价值和对应所需的时间,目标是最大价值。

作出以下定义

定义dp[i][j]为采前i朵,消耗时间j内的最大价值    不难得出以下两种情况1.当前时间可以采走这支草药  (1)如果要采这支采药,那先前状态就要预留j-t[i]时间来满足定义  (2)如果不采那最大价值就是先前状态dp[i-1][j]  因为不清楚哪一种情况更好,但是我们只需要最大值,所以max  综上dp[i][j]=max(dp[i-1][j],dp[i-1][j-t[i]]+v[i]);2.当前时间不够采走这支草药,采不了那就不采,继承先前状态.    即dp[i][j]=d[i-1][j]或者说延续用上文的想法,n支草药价值最大我不知道如果只有1支草药呢?,那我是不是就知道了1支草药知道了,那我2支草药是不是也知道了

然后...直接从基础状态循环到结束,即从第一支草药开始循环。

显而易见不能从采最后几朵开始往前判断,前面状态都不清楚,怎么可以从后面开始。

AC代码

#include using namespace std;int T,m,t[101],v[101],dp[101][1001];int main(){    ios::sync_with_stdio(false);    cin.tie(nullptr),cout.tie(nullptr);    cin>>T>>m;    for(int i=1;i>t[i]>>v[i];    for(int i=1;ilose[i]>>win[i]>>use[i];    }    for(int i=1;im;    for(int i=1;i>t[i]>>v[i];    }    for(int i=1;in>>m;    for(int i=1;i>a[i];    for(int i=0;i

上一篇:怎么将笔记本改成主机

下一篇:部提概念深度解析,带你全面理解部提的含义与重要性