一.问题引入
假设这个小人一次可以走一步或者两步,那么到达台阶顶有多少种方法?
像遇到这种复杂的问题,我们可以使用分治法,将大问题拆解为小问题.
假设是5节台阶,那么我们假设最后一步是一步的情况,那么我们需要算出到4节台阶的方式种数.
如果我们假设最后一步是两步的情况,那么我们需要算出到3节台阶的方式种数.
简化就是:f(5)=f(4)+f(3),递推那么f(4)=f(3)+f(2),f(3)=f(2)+f(1)
因为f(2)和f(1)可以一眼看出,我们可以当成已知条件,f(2)为2种方式(两步都为1步或者一次两步),f(1)为1种方式.
现在我们就可以用分治来具体实现了,这是用种自顶向下的分析.
二.分治法实现
运行结果:
三.分治法弊端
但是弊端也很明显,会出现非常多的重复的计算,而且栈区的空间很快就会被挤爆.
假设我们算6节台阶的话:
当我在递归f(5)的时候已经计算了f(4),f(3)这些,但是当我递归f(4)的时候又要计算f(4),f(3)就导致了大量的重复的计算,实在是不可取.
四.动态规划实现
既然自顶向下的分析走不通,我们何不自低向上进行分析了.
我们知道f(1)和f(2)的值,那么我们就可以算出f(3),如果将f(3)的值保存,我们就可以算出f(4)…
那我们就用一个动态数组来保存值吧:
运行结果:
可以飞快的算出,但是分治法非常慢,而且还有可能栈区满而程序崩溃.
五.动态规划的使用
1.是什么
动态规划也是一种分治思想,但是是自低向上,先求解最小的子问题,把结果存储在表格中,可以避免重复的计算.
2.什么时候用
一个问题可以分解为若干个子问题,并且小问题之间也存在重叠的子问题的时候.
3.使用步骤
- 判断题意是否为找出一个问题的最优解
- 从上往下分析问题,大问题可以分解为子问题,子问题中还有更小的子问题
- 从下往上分析问题,找出这些问题之间的关联(状态转移方程) eg:f(n)=f(n-1)+f(n-2)
- 讨论底层的边界问题 eg:f(1),f(2)
- 解决问题(通常使用数组进行迭代求出最优解)
2024年8月17日11:11:08