DP心得
动态规划是把一个问题分成若干个子问题,其中每一步求取最优的解,然后把这些解保存下来,再利用这些已有的解推出之后所要求的。应该满足如下条件:
1.最优子结构:
对于所要求解的最终问题,我们要求出其最优的解。而这个问题可以分为很多个与最终问题相似的子问题,对于每个子问题我们求出其最优的解,再运用这些最优子问题的解来推导出最终问题。因为问题与子问题相似故可以用相同的方法从最简单(即规模最小的那个子问题)层层递推,直到得到最终问题的解。
最优化原理可这样阐述:一个最优化策略具有这样的性质,不论过去状态和决策如何,对前面的决策所形成的状态而言,余下的诸决策必须构成最优策略。简而言之,一个最优化策略的子策略总是最优的。一个问题满足最优化原理又称其具有最优子结构性质 [8] 。
2.无后效性。
对于每一个阶段而言(问题),所要求出的最优策略(对于该问题的最优解)只有当前的状态决定(当前所记录的本问题的子问题的解),而不直接受之前的状态决定。状态对应于对之前求出的子问题情况的一个总结,是一个客观条件。
状态的这个性质意味着过程的历史只能通过当前的状态去影响它的未来的发展,这个性质称为无后效性 。
动态规划的一般思路:
1.将原问题拆分为子问题。(子问题具有和原问题相同或类似的求解方式)。
2.确定状态。(注意把历史交代清楚,这与之后的第四步,如何推导状态转移方程相关思考具有哪些参数才能进行后续推导。)
3.初始化开始状态。
4.确定状态转移方程。(如何利用当前的子问题的最优解推出当前问题的最优解)
线性dp:
最长上升子序列
dp[i] 以第i个元素作为结尾的最长上升序列元素数
为何如此定义?
可能因为对应上文第二点,我们需要将历史交代清楚,如果dp[i]是前i个元素最长上升序列数,那我们不知道它的最后一个元素是啥,就无从往后推导。
转移方程:
dp[i]=maxd(dp[i],dp[j]) j<i&&lst[j]<lst[i]
和最大的连续串
dp[i] 以第i个元素结尾的和最大的串
dp[i]=max(lst[i],dp[i-1]+lst[i])
最长公共子序列
dp[i][j] 序列a前i个元素和序列b前j个元素的最长公共子序列
dp[i][j]= dp[i-1]+dp[j-1] ,a[i]=b[j]
= max(dp[i-1][j],dp[i][j-1]) ,a[i]!=b[j]
区间dp:
石子合并:
有n堆石子,每相邻两堆石子合并会产生相邻两堆石子总合的贡献,问怎样使石子合并为一堆总贡献最大。
dp[i][j] i到j合并的石子的最大值
dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]+sum[i][j]) ,i=<k<=j
使用记忆化搜索dfs