详解动态规划

详解 \(DP\)

什么是 \(DP\)

动态规划 \((Dynamic Programming ,DP)\) 就是将大问题转化成小问题去处理。

动态规划常常适用于有重叠子问题和最优子结构性质的问题

注意点一:

在 OI 中,计数等非最优化问题的递推解法也常被不规范地称作 DP
----OI Wiki

什么是状态?

状态,用来描述某一问题的子问题的解。

什么是状态转移方程?

状态转移方程是动态规划中本阶段的状态往往是上一阶段状态和上一阶段决策的结果。
---百度百科

简单点来说,状态转移方程就是用来描述由之前状态推出目前状态的解的方程。如这道题目的 \(dp_i=dp_{i-1}+dp_{i-2}\)

都有贪心了,为什么还要 \(DP\)

贪心就是局部最优解就是全局最优解,但有些题目不是,举个最简单的栗子,数字三角形

这道题目,对于每一次移动,我们不一定一定要移动到某一节点能移动到最大的,观察样例,如果按贪心算法,是 \(7 \rightarrow 8 \rightarrow 1 \rightarrow 7 \rightarrow 5\),和是 \(28\) 但如果走 \(7 \rightarrow 3 \rightarrow 8 \rightarrow 7 \rightarrow 5\) 和就是 \(30\)!更大了!所以,这就是 \(DP\) 的重要性!

这道题目的状态转移方程:\(dp_{i,j}=max(dp_{i-1,j},dp_{i-1,j-1})+num_{i,j}\)

两种 \(DP\) 形式

我们可以用 我到哪里去 和 我从哪里来 两种算法来解决 \(DP\),第一个我到哪里去是主动更新其他的状态,而我从哪里来其实就是刚才的,即通过之前的状态的解被动更新自己的解。

记忆化搜索

我们在进行搜索的时候,经常会又“浪费”

就如斐波那契额数列,

int fib(int x){
if(x==1||x==2)return 1;
else return fib(x-1)+fib(x-2)
}

这个其实会有许多浪费,也就是说对于任意一个 \(fib_i\) 都会计算多次!那么我们可以定义一个 \(visit\) 数组,表示这个是否计算过,在定义一个 \(fibo\) 数组,代表如果计算过它的值是多少,这个和并查集的路径压缩有一点点类似(注意是类似)。

题目推荐

背包问题

背包问题有很多种,篇幅有限,请大家到 OI Wiki上查看。

优化

\(DP\) 其实有很多优化,这边主要讲空间优化。

有时候我们目前的状态的解可能只依靠之前一步或之前两步的解推出来的,那我们为什么还要存一个 \(dp\) 数组呢?我们可以直接存 \(last,lastt\) 来表示上一步和上上步,那么对于这道题目,每次dpnow=last+lastt,lastt=last,last=dpnow这样就能优化许多空间。

More

\(DP\) 是一个庞大的家族,它有着许多分支,树形 \(DP\),区间 \(DP\) 等等,甚至还影响到最短路的 \(Floyd\) 由于篇幅有限这里不能讲了,深感抱歉(其实是作者好多不会)。

posted @ 2021-08-17 13:19  WiccldCute  阅读(161)  评论(0)    收藏  举报