代码改变世界

动态规划再思考

2016-07-22 16:23  shuaihanhungry  阅读(501)  评论(0编辑  收藏  举报

动态规划一般用来求解最优化问题。需要注意的是它与贪心算法的区别,贪心算法也是用来解决最优化问题的。动态规划和贪心算法都需要满足最优子结构特征,不同的是动态规划还需要满足重叠子问题特征,而贪心算法还需要满足当前最优解即是全局最优解的特征。

实现动态规划算法

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问题还有:

参考:《算法导论》、夜深人静写算法