用树解释动态规划
先看题leetcode
先想想动态规划怎么解:
以上就是一个简单的动态规划思路。
朴素思想
枚举法
- 查看所有的子数组
- 判断是不是上升的
- 找到最长的
那么怎么枚举呢?
- DFS深搜
- BFS广搜
先画出能够枚举的树
以数据nums = [10,2,3]为例子
- 每一步都有动作(Action): 加入num[i]
- 每个动作伴随着决策,是否留下num[i]
- 最后能够枚举出所有情况
- 每个节点的重要属性只有两个,用什么结尾, 长度多少
如何进行优化
一颗树如何进行优化?
- 剪枝, 剪掉次优的情况
- 备忘, 复用相同的情况
这里就需要策略:
朴素的思考哪些节点是无意义的
或者思考哪些节点可以变成一族,取最优。
按剪枝思路来算
那么有两个要剪枝的情况
- 同样长度的,选择结尾值更小的
- 同样结尾的,选择长度更长的
- 总之,长度越长越好, 结尾越小越好,那么可以新建一个函数F(X), 输入长度,结尾,输出他们俩的和,比较排序?这个不行
总之如果只考虑1,和2两点, 那么可以用hash实现快速剪枝,筛选。
如果要全部考虑,那么需要用一些复杂数据结构,优先级队列,可拓展线段树之类的。
这里不具体展开。
经过剪枝
不难看出,效果已经大大的有了,哟西!good!excelent!
那么dp的思路放到树中是什么样子呢
可以看出复杂度在n**2
不难看出,模型模型一致时,dp可以简单的用树来表示。
总结
以上只是一个例子,实际操作可能会遇到种种困难。不过只要认真分析,基本都没什么问题。
那么总结一下,dp一般怎么搞?
dp的关键时将问题的模型变得具有最优子结构:
当前问题的最优解,包含子子问题的最优解。
树一般怎么搞
枚举!枚举!枚举!枚举!枚举!枚举!
当dp与树用同一套思路时
dp是:
可以看到,很多子情况被复用了,充分体现了最优子结构。
看上去是图了,但是关系并不复杂,有着明显的层级关系。
也许在部分情况下有着更加复杂的拓补结构
更通常的来说
- 能够从若干个子情况中选出最优的那几个,其他的全部剪掉。
如何统一二者
dp之所以很多时候和树不一样,关键是,几大要素没掌握好。
二者共同具有的要素
- 节点的性质,也就是状态
- 节点的粒度,节点代表什么,是当前元素最优,还是当前组最优
- 活动,活动代表着产生分支
- 决策,如何选出最优,进行剪枝
综上所述,可以在构建树时,尽量考虑最优子结构性质,这样就能较好的把握题目。