基础型动态规划(线性动态规划):
动态规划最简单的便是入门时的一些基础题,比如LCS, LIS,数字三角形,背包问题,邮局问题,最大子序列和等。这些题也可以衍生出难题,这里的难主要是状态难想,或者想出来的动态规划算法比最佳解答复杂度高。如经典的LCIS,实际上可以用O(N^2)的算法解出来;再如各种优化,比如LIS可以优化到O(NlgN)的时间。
状态压缩动态规划(似乎也叫插头DP):
这一类算法出现的时间并不太久,典型的题目就是铺砖问题。POJ上有很多类似地题目,就是给了若干种不同形状的瓷砖,问铺满一个房间有多少种方案。二十多年前这些题目被认为是搜索的典型题,技巧主要是构造沟壑是递归函数尽快遇到不满足条件的地方然后返回,也就是说剪枝。但现在的OIer和ACMer一般都用状态压缩动态规划来解,网上可以搜到很多例子,就不详细解释了。
区间上的动态规划:
典型的问题是矩阵链乘、石子合并,能量项链。它们的主要特点是用一个区间做状态,每个区间的最优解依赖于它的子区间。一般来说写成循环的话要先按照区间长度递增的顺序在最外层枚举。如果问题是线性的(如矩阵链乘、线状石子合并)很简单;如果是环状的(如环状石子合并,能量项链),一般有两种处理方法:其一是将环展开成线性的(比如有N堆石子摆成一圈,那么就认为有2N堆石子摆在一条线上,其中第j堆和第N+j堆石子数目一样),其二是设置状态时允许循环(比如用f[i][j]表示从第i堆石子开始,顺时针合并j堆石子所能得到的最大/小值)。
凸多边形上的动态规划:
这就是一般所说的最优三角剖分问题。这样的问题一般不宜用对角线来划分子问题,而是选定一条边,然后枚举另一个顶点和这条边组成三角形,用三角形来将本来的凸多边形划分成两个小凸多边形。这个问题事实上更像上面区间动态规划所说的线性问题,而非环状问题,因为子问题不会绕回去。例如,选取边V1Vn, 枚举顶点Vk,此时将原多边形划分为V1V2...Vk和VkVk+1...Vn两个部分,有点儿类似于矩阵链乘中在位置k最后一次加括号,而分成的两个子多边形并不穿过划分所用的三角形V1VkVn。而不像能量项链中那样,最后一次合并有可能是在第一和第N个珠子之间,也有可能是在其他两个珠子之间,而把这两个珠子提前合并掉了……、
集合上的动态规划:
如求最短Hamilton回路等。特点是虽然是动态规划,但它是指数时间的复杂度,以一个集合为基础进行状态转移。故仅用于问题规模很小的时候(一般都是n<32,以便将一个集合用二进制表示在一个int中,同时也不至于运行时间太长,因为它是指数时间的)。
http://taptree.lofter.com/post/6cb74_5a2db7