动态规划思想中包含了贪心思想、和记忆化思想。
其中,记忆化思想是主体思想(同一件事情不做两次,保证每一个状态最多只处理一次),这样保证了动态规划的高效性。
动态规划的特点是:
- 大问题可以划分若干个子问题(子问题与大问题性质相同但是规模变小)
- 计算子问题中存在重叠的部分
处理动态规划的要点:
- 要会用问题的特征参数描述当前问题
- 状态转移方程(状态值之间的关系)(最重要的一点,找到状态转移方程,问题也就基本解决了)
实现动态规划的方式
- 从顶向下(记忆化搜索形式)
从底向上(递推形式,高层计算依赖于低层的状态(结果))
最简单的例子是Fibonacci sequence(斐波拉契数列),给出一个数n, 求第n个斐波拉契数F(n)。
首先函数的递归出口是
if(n == 1) return 1;
else if(n == 2) return == 1;
else return F(n - 1) + F(n - 2);
可以看到如果单纯使用递归,存在着大量重复的计算。
比如n == 10, 求 F(10)。那么F(10) = F(9) + F(8);
而 F(9) = F(8) + F(7)…….然后当我们计算F(10)右边的F(8)时,其实我们在F(9)过程中已经计算过了F(8)但是计算机不知道,所以存在着大量的重复计算。
改进方法:记忆化思想
我们可以用一个数组保存结果。这样计算F(10) , a[10] = a[9] +a[8], 它就只会去找a[9] 与 a[8] 的值,不会再去查找之前的值。