标签:规划 角度 code 遍历 推导 要求 增加 etc 子序列
动态规划既是一种数学优化的方法,同时也是编程的方法。
第一个难点,不仅是为了避免重复的计算,也是推导状态转移方程的关键。这一难点往往是在把问题规模缩小的过程中进行的。
解决技巧:假设已经把所有子问题的最佳结果都计算出来了,那么只需要考虑,如何根据这些子问题的结果来得出最终的答案。
线性,就是说各个子问题的规模以线性的方式分布,并且子问题的最佳状态或结果可以存储在一维线性的数据结构里,例如一维数组,哈希表等。
解法中,经常会用 dp[i] 去表示第 i 个位置的结果,或者从 0 开始到第 i 个位置为止的最佳状态或结果。例如,最长上升子序列。dp[i] 表示从数组第 0 个元素开始到第i个元素为止的最长的上升子序列。
求解 dp[i] 的复杂程度取决于题目的要求,但是基本上有两种形式。
第一种形式,当前所求的值仅仅依赖于有限个先前计算好的值,也就是说,dp[i] 仅仅依赖于有限个 dp[j],其中 j < i。
举例:求解斐波那契数列
解法:dp[i]=dp[i?1] + dp[i?2],可以看到,当前值只依赖于前面两个计算好的值。
第二种求解 dp[i] 的形式,当前所求的值依赖于所有先前计算好的值,也就是说,dp[i] 是各个 dp[j] 的某种组合,其中 j 由 0 遍历到 i?1。
举例:求解最长上升子序列。
解法:dp[i]=max(dp[j]) + 1,0 <= j < i。可以看到,当前值依赖于前面所有计算好的值。
区间规划,就是说各个子问题的规模由不同的区间来定义,一般子问题的最佳状态或结果存储在二维数组里。一般用 dp[i][j] 代表从第 i 个位置到第 j 个位置之间的最佳状态或结果。
解这类问题的时间复杂度一般为多项式时间,对于一个大小为 n 的问题,时间复杂度不会超过 n 的多项式倍数。例如,O(n)=n^k,k 是一个常数,根据题目的不同而定。
举例:最长回文子串
在普通的线性规划和区间规划里,一般题目有两种需求:统计和最优解。
这些题目不会对输出结果中的元素有什么限制,只要满足最终的一个条件就好了。但是在很多情况下,题目会对输出结果的元素添加一定的限制或约束条件,增加了解题的难度。
举例:0-1 背包问题
标签:规划 角度 code 遍历 推导 要求 增加 etc 子序列
原文地址:https://www.cnblogs.com/JasonBUPT/p/11868558.html