动态规划一般用来求解最优化问题。需要注意的是它与贪心算法的区别,贪心算法也是用来解决最优化问题的。动态规划和贪心算法都需要满足最优子结构特征,不同的是动态规划还需要满足重叠子问题特征,而贪心算法还需要满足当前最优解即是全局最优解的特征。
实现动态规划算法
1、描述最优解结构特征。做出第一个选择,并假设已经知道该选择是最做优的,刻画做出该选择后的子问题空间,用剪切粘贴法证明子问题的解就是原问题最优解的组成部分。
2、递归地定义最优解值。保证子问题空间尽可能简单,即维数尽可能低,只有在必要时才扩展它,增加维数。
3、采用自底向上法计算最优解,即先计算子问题的解。子问题空间的维数基本确定了循环的层数。
4、利用计算出的信息构造最优解,即利用子问题的解构造原问题的解。其中经常用到min或max,及更小的子问题的解的结果。
动态规划的经典模型有
1、线性模型。
2、区间模型。
3、背包模型。
4、状态压缩模型。
5、树状模型。
动态规划的常用状态转移方程
如果子问题的数目为O(nt),每个子问题需要用到O(ne)个子问题的结果,那么我们称它为tD/eD的问题,为了方便,把opt作为取最优值的函数(一般取min或max),w(j, i)为一个实函数,其它变量都可以在常数时间计算出来。于是可以总结出四类常用的状态转移方程:
1、1D/1D,d[i] = opt{d[j] + w(j, i) | 0 <= i < j}, (1 <= i <= n)
。
2、2D/0D,d[i][j] = opt{d[i-1][j] + xi, d[i][j-1] + yj, d[i-1][j-1] + zij}, (1<= i, j <= n)
。
3、2D/1D,d[i][j] = w(i, j) + opt{d[i][k-1] + d[k][j]}, (1 <= i < j <= n)
或d[i][j] = opt{d。[i-1][k] + w(i, j, k) | k < j}, (1<= i <= n, 1 <= j <= m)
。
4、2D/2D,d[i][j] = opt{d[i'][j'] + w(i', j', i, j) | 0 <= i' < i, 0 <= j' < j}
。
典型问题简单分析
1、钢条切割问题
子问题数目为O(n1),每个子问题需要用到O(n1)个子问题的结果,属于1D/1D问题。
2、矩阵链乘法问题
子问题数目为O(n2),每个子问题需要用到O(n1)个子问题的结果,属于2D/1D问题。
3、最长公共子序列问题
子问题数目为O(n2),每个子问题需要用到O(n0)个子问题的结果,属于2D/0D问题。
4、其它问题
1)1D/1D问题还有:
问题1、300. Longest Increasing Subsequence
Given an unsorted array of integers, find the length of longest increasing subsequence. For example, Given [10, 9, 2, 5, 3, 7, 101, 18], The longest increasing subsequence is [2, 3, 7, 101], therefore the length is 4. Note that there may be more than one LIS combination, it is only necessary for you to return the length.
这是个很简单的一维动态规划问题,状态转移方程为dp[i] = max{dp[j] | j < i && nums[j] < nums[i]} + 1
,代码如下,时间复杂度还可优化到O(nlogn)。
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
const int size = nums.size();
if(size == 0) return 0;
vector<int> dp(size, 1);
int ans = 1;
for(int i = 1; i < size; ++i) {
for(int j = 0; j < i; ++j) {
if(nums[j] < nums[i]) {
dp[i] = max(dp[i], dp[j] + 1);
}
}
ans = max(ans, dp[i]);
}
return ans;
}
};
2)2D/0D问题还有:
问题1、二维动态规划——Palindrome
问题2、二维动态规划——Interleaving String
问题3、5. Longest Palindromic Substring
3)2D/1D问题还有:
4)2D/2D问题还有:
参考:《算法导论》、夜深人静写算法。