• 动态规划总结


    动态规划一般都是求最值问题,或者该问题的本质是求最值。
    动态规划的本质是穷举,根据dp本身的定义写出状态转移方程,各个状态会有自己的范围,那就从中选出最大值,选择的方法是都试一遍找最大值。

    动态规划思考与书写的流程:
    1.根据题目想明白 状态 & 选择 & 结果
    结果往往指的是题目要求的东西,比如说求最小操作数,那么结果就是在xxx条件之时的最小操作数;状态指的是真正能对结果产生影响的变量,状态的理解与设置往往决定了一个动态规划的基础,题目中会展示一些变量,我们可以在此基础上进行思考,但二者并不是完全一致;选择则是在每个状态下拥有的不同结果(选与不选,哪一种特定操作,或者是不同的结果,这里对于不同的结果理解上会不舒服,因为选择是相对主动的操作,而结果是相对被动的事情,但其实本质上是一样的,因为对dp的每一个状态,都要去穷举其各个情况,所以这里可以认知为“穷举各种可能”)。

    2.写出dp的定义 (主要利用状态和结果,在xxx状态下,结果为uuu)
    dp往往有两种,dp[] 数组 或者 dp函数,但本质上是一样的,dp[] 往往用于自底向上的定义,写起来简单,缺点是会有索引偏移,dp函数是用于带有备忘录的自顶向下的定义,写起来复杂一点,一般来说,同一个dp定义,这两种都可以写出来,只不过自底向上是[0.........i] 的情况,最终输出dp[n] 的值,而自顶向下的是[i........末尾]的情况,最终输出dp(0)。这一步最关键的在于自己要能用自然语言解释dp定义,比如“在可用鸡蛋为k,搜索的目标范围为n的情况下所需的最小操作数”,这样方便与写出状态转移方程。

    3.写出状态转移方程 (利用选择)
    这是在dp定义好之后,根据dp的定义和选择,写出状态转移方程,大概是dp[x] = max (选择1,选择2,选择3) = max(dp[x-1], dp[x-2]+2..)
    这里是最关键的一步,虽然思考的过程应该在上一步就完成。

    4.写出base case
    base case就是那些不用算,仅靠逻辑分析就可以直接得出结果的极端情况,用于启动整个动态规划的运算。写全base case还是需要一点经验。

    5.穷举
    根据base case和状态转移方程写出穷举的方式。这里其实有两种,第一种是递归模式,也就是把所有的都丢进递归,最终由base case开始运算,另一种是状态遍历,即

    for 状态1 in 状态1的所有取值:
        for 状态2 in 状态2的所有取值:
            for ...
                dp[状态1] [状态2] [...] = 择优(选择1,选择2...)
    

    这里的择优也就是max,min.....,可以画个图来看应该如何遍历,要确保状态转移方程需要的条件是足够的,dp[i][j]dp[i+1][j-1]dp[i+1][j]dp[i][j-1]都有关系的话,那这三个方向都得知道才能继续往下算。

    一些经验:
    1思考的时候要想明白,状态转移方程是为了计算,即是为了从已知得到未知,以自底向上为例:找到的关系式一定是[i] [j] = 择优([i-1] [j-1] , [i] [j-1], [i-1] [j] ),一定是按照顺序(自底向上还是自顶向下)的已知到未知。

    2两种穷举模式,都是首先设定base case,状态遍历时用for直接从base case开始往下计算,递归则是写出状态转移方程,这里面自然是包含递归的,依次递归到base case,再自动算回来。

    3最关键的是定义dp与找到状态转移方程,找到之后,若为自底向上则设数组直接写,但可能为了base case要索引偏移;若是自顶向下,那么就设函数dp,函数dp有时候比数组更好操作!!!,这里往往会设置一个备忘录,memo,其实memo[i] [j] 就是记录dp[i] [j] 的值。

    int[][] memo=new int[m][n];
    Arrays.fill(memo); //给memo设上特殊值,特殊值一定要在正常值的取值范围之外,表示该处的dp没有计算
    int dp(int x,int y){
        //memo在该处不是特殊值,就表示已经计算过了,直接返回
        if(memo[i][j]!=特殊值){
            return memo[i][j];
        }
        
        //在该处是特殊值,说明未计算过,那么就需要用状态转移方程来计算
        return 状态转移方程;
    }
    
  • 相关阅读:
    《大数据——大价值、大机遇、大变革》试读
    div+csS中的一些技巧和浏览器兼容的办法
    js正则表达式
    布局 IE haslayout
    几个好的网站
    ie6 几个li上下排列会闪动的问题,嵌套div—外层div内层div都设置背景颜色,内层div背景色不显示的问题
    live()解决Jquery采用append添加的元素事件无效和获取不到添加元素的值
    SQL语句写返回一天内的纪录,得到一周内星期几的时间
    网易邮箱添加附件功能原理浅析转
    实体类序列化
  • 原文地址:https://www.cnblogs.com/shiji-note/p/14461232.html
Copyright © 2020-2023  润新知