算法之动态规划

动态规划

动态规划的求解思路:

动态规划可以说是一种思想:自上而下分析问题,自下而上解决问题。

什么意思呢,就是把一个大问题分解成若干个小问题,对每个小问题求解,求的解存储在一维数组或者二维数组中。
然后自下而上解决问题,意思就是每个小问题求解完毕后,再去求解较大的问题,直到最后问题解决。

将原问题拆解成若干子问题,同时保存子问题的答案,使得每个子问题之求解一次,最终获得原问题的答案。

经典动态规划题:

斐波那切数列:

\[f(n)=\begin{cases} 1, & n = 0 或 1\\ f(n - 1) + f(n - 2), & n >= 2 \end{cases} \]

斐波那些数列可以用递归的方式实现,也可以用动态规划的思想解决。

首先递归的求解过程中有很多重复计算,比如计算f(5)要先计算f(4)和f(3)。 计算f(4)的时候又去计算f(3)和f(2).
可见其中有很多重复计算。
我们将每个小问题的值放到一个数组中,来避免重复计算。

比如

int[] dp = new int[n+1];

for (int i = 2; i <= n; i++) {
    dp[n] = dp[n - 1] + dp[n - 2];
}

这样通过O(n)的时间就能计算出对应的dp[n]也就是f(n)的值。

这就是动态规划思想的一种体现。

自上而下分析问题,将f(n)分解为f(n - 1) + f(n - 2)
自下而上解决问题, 先求dp[2], 再求dp[3], ... , 直到dp[n]

而实现这种做法的关键是
1.找到状态转移方程,即斐波那切数列中的f(n) = f(n - 1) + f(n - 2)。但是大部分问题不会直接给出状态转移方程,需要自己摸索。
2.就是合理的存储方式。一维数组,二维数组等等保存自下而上已经求解的问题的值。

在我看来最难得还是状态转移方程。需要多加练习。

动态规划题的一些特点:

就是现在手里有个题,怎么看这个题是不是一个动态规划的题。

就我的经验来看,有如下一些特征的题都可以考虑用动态规划。

第一看能不能用递归来做
第二就是有没有重复状态
第三就是尝试找一下状态转移方程

还是多做吧,咱做得少,咱也总结不出来。
最骚的是当你他妈的好不容易用动态规划做出来一道题。
发现这道题可以用dfs,可以用贪心,可以用数学方法。日。

posted @ 2022-06-26 17:23  cfdroid  阅读(12)  评论(0编辑  收藏  举报