第三章作业
1.1 最优子结构、递归方程、边界条件
状态定义
设 dp[i][j]:从起点(1,1)走到格子(i,j)的最小通行总费用(包含格子(i,j)本身的费用);
a[i][j]:格子(i,j)的通行费。
最优子结构说明
到达(i,j)只有两种可能:从上方(i-1,j)向下走一步,或者从左侧(i,j-1)向右走一步。
到(i,j)的最优路径,一定是【到(i-1,j)最优】或者【到(i,j-1)最优】再加上当前格子费用,满足最优子结构。
递归方程
dp[i][j]=a[i][j]+\min
\begin{cases}
dp[i-1][j] \
dp[i][j-1]
\end{cases}
\quad (i>1,\ j>1)
边界条件
- 起点:\boldsymbol
- 第一行(只能从左边过来,不能从上面来):
dp[1][j]=dp[1][j-1]+a[1][j],\quad j=2,3,\dots,N - 第一列(只能从上面过来,不能从左边来):
dp[i][1]=dp[i-1][1]+a[i][1],\quad i=2,3,\dots,N
1.2 填表维度、填表范围、填表顺序、原问题最优值
• 表的维度:二维表,\boldsymbol{N\times N} 的dp表。
• 填表范围:i\in[1,N],\ j\in[1,N]
• 填表顺序:逐行从上到下,每行内部从左往右。
原因:计算dp[i][j]时,它上方dp[i-1][j](上一行,已经算好)、左边dp[i][j-1](本行左边,已经算好),保证依赖项先计算完成。
• 原问题最优值:\boldsymbol{dp[N][N]}(右下角单元格)。
1.3 时间、空间复杂度
• 时间复杂度:\boldsymbol{O(N^2)}
一共N^2个状态;每个状态只做一次min比较和一次加法,是O(1)操作。
• 空间复杂度:\boldsymbol{O(N^2)}
需要N\times N的dp数组存储状态。
补充优化:因为当前行只依赖上一行和本行左边,可以用一维滚动数组压缩,优化为O(N),基础版本写O(N^2)即可。2. 对动态规划算法的理解和体会
动态规划的核心是拆分、复用、避免重复计算,它适用于同时满足最优子结构和重叠子问题的问题。
-
最优子结构:一个问题的最优解,可以由它子问题的最优解推导出来;
-
重叠子问题:递归分解的时候,很多子问题会被反复计算,暴力递归会大量重复,DP用一张表把子问题结果存下来,算一次永久复用;
-
和贪心区别:贪心只看局部最优,不一定能推出全局最优;动态规划会记录所有子问题最优,在多个选择里挑最优;
-
解题套路一般是:定义状态 → 找状态转移方程(递归式) → 确定边界 → 规划填表顺序;
-
代价:动态规划是以空间换时间,用数组保存子问题答案,大幅降低暴力搜索的指数复杂度。
简单来说:动态规划就是把大问题拆成小问题,把小问题答案存起来,一步步推到大问题的答案。
浙公网安备 33010602011771号