对dp的理解-csdn博客
dp全称动态规划,是一种很重要的算法思想。动态规划的算法与分治算法有相似之处,又有这截然不同的差异。动态规划的思想主旨是将待解的问题分成若干个子问题,先求解子问题,然后在从这些子问题再得到原有问题的答案。从中我们可以很明显的抽出一下几个内涵:
1.要把问题进行划分。也就是要根据问题实际计算的过程,把每一步都分解出来,然后找出这些子问题的解决方法,总的问题可能会难以找出答案,但是分解到最后的子问题一定要能够找出答案来。
2.根据子问题要能够得出总问题的答案,也就是我们所说的递推方程。在这里,我不说是递推方程,而之说要找到从子问题到总问题的答案。我们在这一步要理清子问题和大问题之间的关系,而这也是用来对第一步的选择,选择那些能够求解的子问题,并且与之相关连的大门题也能够从中找到解题思路。
3.实现记录子问题的功能。这其实也是记忆化数组,从第二个内容中我们可以看到,总问题是要根据子问题的答案而得出的,然而我们有些时候并不能够保证算出自问题后,就直接可以求出所有的与之相关的大问题的答案。因此,这里就应该根据题意开出一个合适的数组,并记录下子问题的答案,这里数组可能仅仅是一个一维的递推数组,也可能是一个多维的子模式数组。
4.代码上的控制。能够快速写出写出完整的代码,对于复杂一点的dp一定要内心有一个清晰的思路,如果记不好的话最后在纸上快速的进行模拟一下,记录出重要的内容,然后根据思路去写。否则不但写代码的时间会非常的长,而且很大可能要调很长时间的bug。
5.dp的难点。dp的框架是一个综合行很强的算法,其中涉及的内容很短,而根据dp内容的侧重点不同可以有着跨度很广的变化。一个侧重与递推关系的dp,主要依赖的数学内容更多,因此有一个好的数学功底也是非常重要的。如果能够找出递推推的方程,那么这种形式的题完稍微有一点代码功底即可。对于子问题很复杂的dp(列如数位dp,一些需要构建多维的dp),其中的关系可能很难找出来,但是那些子问题和总问题都有一个简单的共性,因此可以具体的构造一个时列,然后就可能得出一个你以前未曾想过的关系式,这类dp也需要对代码要有一个很好的控制。还有一类dp既非常考验思维,有非常考研代码能力的。列如状压dp,这种题是要把状态压缩成数组的一维或几维,然后这里面的关系可能是那种非线性的变化,可能是与计算既运算法则有关的变化。
总之,dp变化很多,不同的侧重点,便可能有着截然不同的解法,能够好的理解dp总会有些用的。最后,dp的种类有很多,但是一些dp是具有自己的模板的,初学者遇到一些这样的题可以直接去先学习一下模板,理解那些模板之后有事候你的思维会自动向那种解法上靠拢的,然后自然而然的就得出了一套解法。但是,模板毕竟是模板,在你深刻理解之后,再去构造自己的思维,然后在整体取思考一下整个框架,才能做到事半功倍的效果。