zoukankan      html  css  js  c++  java
  • 动态规划再思考

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

    实现动态规划算法

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

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

  • 相关阅读:
    @Value和@ConfigurationProperties
    mongodb为集合新增字段、删除字段、修改字段(转)
    mongoTemplate CURD 和模糊查询(转)
    在项目中使用Swagger接口说明
    mongodb 批量添加、修改和删除
    @SpringQueryMap注解 feign的get传参方式(转)
    Spring下的@Order和@Primary与javax.annotation-api下@Priority【Spring4.1后】等方法控制多实现的依赖注入(转)
    @RequestBody和@RequestParam区别
    Juit4 SpringBoot注解
    Spring Boot干货系列:(十二)Spring Boot使用单元测试(转)
  • 原文地址:https://www.cnblogs.com/shuaihanhungry/p/5695624.html
Copyright © 2011-2022 走看看