我才六年级,我还不太熟悉dp呢,喷可以,但喷轻点谢谢
还有本篇未使用标准的Markdown规范文章模板及LaTeX,不要骂!
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
在做DP题目时,常常会遇到正常定义无法解决的问题
这里就拿一些例题随便聊聊
1. 如何确定dp数组的维度与含义?
个人认为着重考虑会对最终答案造成影响的方案/条件
2. 推导相应的状态转移方程
可以考虑以下几个方面
1. 数组有几维?
2. 每个维度表示什么?存储什么信息?
3. 转移过程中信息不够,缺乏关键信息 -> 考虑扩维
4. 空间复杂度过高 -> 考虑降维(或许也可以优化)
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
对于这道例题,会发现如果将dp[i][j]定义为以a[i][j]为右下角的最大正方形边长,实际上无法确定“01交替是否可行”(个人随意起的名字)。因此需考虑扩维
个人认为,扩维没有标准的方法,思维在这时就尤为重要,思维发散一点,或许可以得到一些收获
所以,这题扩一个维度即可,设置dp[i][j][0/1]为以(i,j)为右下角点且当前点的颜色为0/1的最大正方形边长
因此,答案一目了然
如果当前这一位是0,则左边及上边的颜色应为1,左上角点应为0
如果当前这一位是1,则左边及上边的颜色应为0,左上角点应为1
代码
例题在这里:最大正方形II
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
新题开始:
对于这道例题,会发现如果将dp[i]定义为前i个数字变为非递减的最小操作次数,实际上无法确定“a[i - 1]此时是多少”(个人随意起的名字)。因此需考虑扩维
所以,这题扩维即可,设置dp[i][j(-1/0/1)]为以(i,j)为前i个数字,最后一个数字(也就是第i-1个数字)是j时,变为非递减的最小操作次数
因此,答案一目了然
状态转移方程不推导了,因为本篇主要分享维度思考
代码
例题在这里: BAJ-BYTECOMPUTER
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
新题开始:
题面较长,限制条件较多(但是这反而更简单?)
第一眼看到这题:简单,max就行了,第二眼:咋有如此之多限制条件?
对于这道例题,会发现如果将dp[i]定义为前i个点种满树的最大观赏值,实际上无法确定“前一项到底是多高的树”(个人随意起的名字)。因此需考虑扩维
第一次扩维:
dp[i][j(0/1/2)]表示前i个点种满树且最后一个点种的树为j时的最大观赏价值。0/1/2分别代表低中高树。
但是这里还是无法确定“i和前面点的高低关系”,如果第i个点比第i-1个点高,下一个就必须要下降,反之则亦然。
继续扩维
dp[i][j(0/1/2)][k(0/1)]
dp[i][j][k] 表示前i棵树所能达到的最大观赏价值和,最后一个点种的树是j,表示第i棵树比左右两棵树都高(k=1),否则相反(k=0)
不过这里还有问题,目前的想法无法实现“环形”,毕竟这次咱们交流维度,继续扩维!
简单来讲,第四个维度就是记录“第一棵树是啥”,这样更好解决“环形”的问题
最终:
dp[i][j][k][l]代表:
考虑前i棵树
最后一棵树高度为j(0/1/2分别代表低中高树)
最后一棵树比它前面的和后面的状态(0代表低,1代表高)
第一棵树的高度为l(0/1/2分别代表低中高树)
时可获得的最大价值
因此,答案一目了然
状态转移方程不推导了,因为本篇主要分享维度思考
代码
例题在这里:教主的花园
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
我感觉会不会补充的维度其实是额外状态?