zoukankan      html  css  js  c++  java
  • leetcode刷题之动态规划

    这一篇是之前在做过一些dp题目之后,总结了一些东西,文章还没最后完成

    动态规划

    1、前言

    动态规划(Dynamic Programming)本身是属于运筹学的一个分支。是解决决策过程最优解的数学方法,

    常常做到动态规划问题,想记录下做过的dp题,遇到简单的还可以想出来一些,但是常常都是有点难度,而且动态规划问题很常见,在一些大厂的笔试面试题中,今天来总结下动态规划。

    2、介绍

    动态规划有个很明显的特点就是可以解决重复的子问题,就是将多次重复计算的子部分省掉,只计算一次,将其记录起来,提高效率。还有一个很重要的特点是存在最优子结构-子部分中有个部分是符合题目的最优解。当然这个结果是在比较之后得出的。

    3、分类

    百度百科上有着详细的分类,遇到比较多的是背包问题,在下面的举例中的也大多是背包问题,背包问题就是简单来说,就一个背包,装东西,怎么装,在满足什么条件去装,从而得到不同的最优结果。

    image-20200520120607437

    4、使用场景以及怎么使用

    使用场景

    首先是什么时候会用到动态规划,一开始我也会模糊这个使用。但总的来说就是遇到一些求最值问题,或者是最优解,往往动态规划都是可以用的。

    同时记住要使用动态规划的前提是必须满足最优化原理(简单说这个解一定是最屌的解,最优解)和无后效性(不受前面影响)。

    最优化原理(最优子结构性质):一个最优化策略具有这样的性质,不论过去状态和决策如何,对前面的决策所形成的状态而言,余下的诸决策必须构成最优策略。简而言之,一个最优化策略的子策略总是最优的。一个问题满足最优化原理又称其具有最优子结构性质。

    过程的历史只能通过当前的状态去影响它的未来的发展,不受之前的影响,当前的状态已经是之前的总结了,未来只能是通过现在去影响了。这个性质称为无后效性。

    使用步骤

    概念

    动态规划中重要的三个概念有最优子结构、边界和状态转移方程。理解好这三个,任何动态规划问题就可以很好很容易解决的。

    最优子结构-指的是不走最后一步或者走最后一步的最优子情况是怎么样的。

    边界是每一个动态规划问题要想有解必须存在的,没有边界就没有答案,就是到某一个解的时候,其没有子解了,它自己已经是最小的了。

    状态转移方程是最重要的,常常看到下面类似这种方程,就是状态转移方程。

    image-20200520123555118

    步骤(当确定了使用动态规划之后)

    1、找到状态

    (小规模问题的数学表示)状态表示阶段开始时的客观条件,当前处于什么的条件

    2、最小状态是什么

    这个也是指边界(最小规模的问题)也是逆推的终点。

    3、列出状态转移方程

    (大规模问题如何转化为更小的问题)确定过程由一个状态转移到另一个状态的演变过程。这个也是最重要的,最难的。

    4、要求的返回值是什么

    题目要求返回什么,就将结果解答出来。因为有时最后的最优状态不是所需的,可能需要输出其他的结果,所以要看清楚题目要求。

    5、动态规划解题思维

    有两种思维,简单的就是从头到尾,还有从尾到头。

    自顶向下

    基本会用递归,大范围开始推算到小范围(后面的最优到最前的最优),注意不断保存着中间结果,避免了重复计算。这里是和运筹学中的逆推解法大同小异。意思是从最终状态开始,逆着实际过程的进展方向逐段求解。直到第一个阶段为止。

    下面举例是熟悉的走楼梯

    一个人每次只能走一层楼梯或者两层楼梯,问走到第100层楼梯一共有多少种方法。

    int[] dp= new int[100];/*用于保存中间结果否则会重复计算很多重复的子问题*/
    int DP(int n)
    {
        //1和2是边界条件
        if(n == 1)
            return 1;
        if(n == 2)
            return 2;
        //状态转移方程
        dp[n] = DP(n-1) + DP(n-2);
        //返回的结果
        return dp[n];
    }  
    

    自底向上

    自小推到大,从小范围到大范围,运筹学中的顺推法,与上面只是方向不一样。

    格式如下,常常伴随着for遍历

    for(int i= 0; i < max; i++){
    	dp[i] = dp[i-1]+dp[i-2]
    }
    

    6、例题

    题目有以下这些推荐---

    image-20200521201817306

    #背包问题

    背包问题也分为了0-1背包和完全背包和多重背包问题

    0-1背包问题

    0-1背包就是每个物品只能用一次,重量价值都是一一对应,放的重量也是有限的。然后求出最大价值的放置方法

    #416

    image-20200521154608816

    image-20200522095124725

    image-20200521154729695

    完全背包

    完全背包问题是物品是无次数限制。其他和0-1一样

    多重背包

    多重背包是物品有次数限制,比如2、3、4这样的

    #5

    image-20200521095345466

    image-20200522094922270

    #983

    image.png

    image-20200522095328825

    7、最后

    动态规划就是解决冗余的。

    借鉴了一些文章如下,感谢,有什么不对的地方大家多多指教,多多留言,觉得写的还可以点个赞hh

    程序员小灰

    知乎

  • 相关阅读:
    05 css继承性
    04 选择器权重
    03 css三种引入的方式
    02 css实现举例
    01 css介绍
    05 dl-添加定义列表
    04 ol-热门点击排行榜
    02 h1 p hr br 特殊符号
    01html简介
    函数内置方法
  • 原文地址:https://www.cnblogs.com/yhycoder/p/12935742.html
Copyright © 2011-2022 走看看