一、什么是动态规划
动态规划是求解决策过程最优化的数学方法。把多阶段过程转化为一系列单阶段问题,利用各阶段之间的关系,逐个求解,创立了解决这类过程优化问题的新方法
1.多阶段
意味着可以分成很多的子问题,子问题的子问题等等~,也就是说,该问题可以拆解成多个子问题进行求解
2.最优子结构
在自下而上的递推过程中,我们求得的每个子问题一定是全局最优解,既然把它分解成了多个子问题,那么我们就可以依赖这些子问题的最优解来求得最优的答案
3.自上而下
怎样才能自上而下的求出每个子问题的最优解呢,当然各个子问题之间是有关联的,即迭代递推公式,也就[状态转移方程],如何定好这个状态转移方程呢,那就需要我们定义好各个子问题的状态(DP状态),为何使用自下而上的解法呢?如果自上而下,采用递归这样的解法,子问题之间可能存在大量的重叠,时间复杂指数会呈指数级上升,而自下而上可以消除重叠的子问题
二、小试牛刀
求最小路径和
如图示,上面的三角形由一串数字组成,要求从顶点2开始走到最下边的最短路径,每次只能向当前节点的下面两个节点走
可得的最优解是2-3-5-1
首先,我们需要一个二维数组来表示三角形的各个节点,a[0][0]是第一行,a[1][0]、a[1][1]是第二行,以此类推
正常的解法是自上而下,每次计算判断一下节点的下面两个节点的最小值,因为比较常见普通,这里就省略了代码,如果我们使用裁剪,其时间复杂度和空间复杂度都为O(n)
如果我们使用自下而上的解法呢?
那么问题来了,如何自下而上的动态归划来解决问题呢?我们这么看,要求节点 2 到底部边的最短路径,只需求得到第二次节点3和4的最短距离,然后取这两者之中的最小值再加上2不就是从2到底部的最短距离了,同理,到节点3和4到下面节点的最短距离,只需求得3和4节点下面节点到节点3和4的最短距离然后比较取最小值即可,依此类推,我们便可求出最优解
#伪代码
#状态转移方程
DP[i,j] = min(DP[i + 1, j], DP[i, j + 1]) + triangle[i, j]
#这个状态状态转移方程代表要求节点到最底部的最短距离只需左右两个节点到底部的最短距离的最小值加上这个节点本身!
func traverse()
{
int row = 4
int[] mini = triangle[row -1] // triangle就是上述的三角数组
// 从倒数第二行开始,因为最后一行是固定的
for(int i = row -2; i >= 0; i--)
{
for (int j = 0; j < triangle[j].length; j++) {
mini[j] = triangle[i][j] + Math.min(mini[j], mini[j+1]);
}
}
return mini[0];
}
三、总结
仔细的回想一下,我们先看题会考虑到递归来求解,在递归中发现了重叠的子问题,如是我们使用剪枝的形式来优化时间和空间复杂度,自然而然地想到了我们也可以用自下而上的动态规划来求解,所以,求解动态规划我们就可以按照这个套路来,最重要的是找出它的状态转移方程,然后自下而上一步一步求解
就先分享到这了,后续有空还会不断的找到leecode的题来分享,nice~