• 动态规划专题——passage_1


    动态规划组成部分:

    1:确定状态

          — 确定最后一步(最优策略)

          — 抽象子问题 

    2:归纳转移方程

    — 不知道且需要的信息,加进状态里

    3:初始条件和边界情况

    4:计算顺序

    — 一般为从左到右,从上到下

     

    例一  最值型动态规划(col1.2)

    题目描述:

    有2 、 5 、 7三种硬币,求最少几枚能拼够一个整数?(3.-2)

    状态转移:

    f[x] = min { f[x-2] + 1, f[x-5] + 1, f[x-7]+1 }  (3.-3)

    初始条件: (3.4)

    f ... -1 0 1 2 3 4 5 6 ... 27
      nan nan 0 nan 1 nan 2 1 3 ... 5

    小笔记:

    感觉入门的动态规划问题还是像由递归延伸出来的记忆化搜索。(2.2)

     

    例二 计数型动态规划

    题目描述:

    [ m , n ]网格,人从(0,0)出发,每步可以向下或向右走一步,有多少种方法走到左下角?

    状态转移:

    f[i][j] = f[i-1][j] + f[i][j-1]

    边界状况:

    i = 0 or j = 0  ——f[i][j] = 1

    初始条件:

    f[0][0] = 1

     

    例三 存在型动态规划

    题目描述:

    n块石头在x轴 0 ... n-1位置,青蛙想从0跳到n-1,在第i块石头上能跳ai,问能否跳到n-1上?

    状态转移:

    f[i] = OR(任意)0<=i<j(f[i] AND i + a[i] >= j ) 

     

    例四 序列型动态规划

    题目描述:

    一排N栋房子,每栋要漆成红、蓝、绿三色之一,相邻不能漆成同色,第i栋房子漆成红、蓝、绿的开销分别是[i][0] 、[i][1] 、[i][2],问漆这些房子的最小花费?

    确定状态:

    最后一栋房子[n-1]必为三色之一,但确定这一状态还需要知道[n-2]的颜色、知道[n-2]为各种颜色时的最小花费。

    边界条件:

    f[0][OR] = 0

    状态转移:

    f[i][0] =min { f[i-1][i] + cost[i-1][0] , f[i-1][2] + cost[i-1][0] }      类比,三个颜色三个方程

     

    例五 划分型动态规划

    题目描述:

    有段A~Z组成的字母串信息被加密成数字串,A-1,B-2,....Z-26,给定加密后字串S[0...N-1],问有多少种解密方式?

    确定状态:

    求前[n-1]和[n-2]个字符解谜方式数之和。

    状态转移:

    f[i] = f[i-1] ( S[i-1]能对应一个字母 ) + f[i-2] ( S[i-2]S[i-1]能对应一个字母 )

    边界条件:

    f[0] = 1

     

    坐标型动态规划

    给定一个序列或网格,需要找到序列中某个/某些子序列或网格中的某条路径

    — 某种性质最大/最小

    — 基数

    — 存在性

    动态规划方程f[i]中的下标i表示以ai为结尾的满足条件的子序列的性质,f[i][j]中的下标i,j表示以格子(i,j)为结尾的满足条件的路径的性质

    — 最大值/最小值

    — 个数

    — 是否存在

     

    例六 一维坐标型动态规划

    题目描述:最长单调连续子序列

    给定a[0],...,a[n-1],找到最长的连续子序列i,i+1,i+2,...,j,使得a[i] < a[i+1] < ... < a[j],或者a[i] > a[i+1] > ... >a[j],输出长度 j - i + 1.

    例:输入  [ 5 , 1 , 2 , 3 , 4 ]

    输出 4

    确定状态:

    找最长连续上升子序列,再将序列颠倒所求就是最长连续下降子序列。

    设f[j] = 以a[j]结尾的最长连续上升子序列的长

    情况一:a[j]  ans = 1

    情况二:a[j-1] < a[j]  ans = ans( a[j-1] ) + 1

    状态转移:

    f[j] = max{1 , f[j-1] + 1 ( j > 0  AND a[j-1] < a[j] ) } 

    计算顺序:

    f[j] =以a[j]结尾的最长连续上升子序列的长度

    max{ f[0] , ... , f[n-1] }

     

    例七 二维坐标型动态规划

    题目描述:

    给定[m , n]网格,每个格子(i , j)里都有一个非负数A[i][j],求一个从左上角(0 , 0)到右下角的路径,每一步只能向下或者向右走一步,使得路径上的格子里的数字之和最小,输出最小的数字和。

    确定状态:

    无论何种方式到达右下,最后一步只有两种可能。

    状态转移:

    f[i][j] = min{ f[i-1][j] , f[i][j-1] } +A[i][j]

    初始边界:

    f[0][0] = A[0][0]            i = 0 OR j = 0,前一步方向唯一

    空间优化:滚动数组

    我们发现计算时我们只用了两行数组,开数组时只用开 f[0][0...n-1] 和 f[1][0...n-1] 交替赋值使用即可。

     

    例八 上难度了

    题目描述:

    给定[m , n]网格,每个格子可能为空,也可能有个敌人,也可能有一堵墙。只能在某个空格子里放一个炸弹,炸弹会炸死同行同列的所有敌人,但是不能穿透墙。求最多能炸死几个敌人?

    输入:

    0 E 0 0
    E 0 W E
    0 E 0 0

    输出: 3

    题目分析:

    每个格子上下左右求一下,时间复杂度指数级。TEL不用想。动态规划的思想,这题确实也不是很好想。

    确定状态:

    将爆炸拆解成四个方向,假设所有格子都能放炸弹,单独计算。

    有敌人的格子,格子里敌人被炸死,并继续向上爆炸。

    有墙的格子,炸弹不能炸死任何敌人。

    则,在(i , j)格放一个炸弹,它向上能炸死的敌人数是:

    — (i , j)格为空地:( i-1 , j )格向上能炸死的敌人数

    — (i , j)格为敌人:( i-1 , j )格向上能炸死的敌人数 + 1

    — (i , j)格为墙:0

    最后求四个方向,max{ Up[i][j] + Down[i][j] + Left[i][j] +Right[i][j] }

    初始条件:

    Up[0][j] = 0,如果(0 , j)格不是敌人

    Up[0][j] = 1,如果(0 , j)格是敌人

    转移方程:

    Up[i][j] = { Up[i-1][j] (如果i , j是空地) OR Up[i-1][j] + 1 (如果i , j是敌人) OR 0  (如果i , j是墙) }

    空间优化:

    可以开一个两行的Up滚动数组,计算四个方向,等规模ans数组存最后结果。

     

    例九 序列 + 位操作型动态规划

    位操作(二进制)

    &与, |或,  ^异或,  !非

    逐位操作

    题目描述:

    给定N,要求输出0 , 1 , ... , N 的每个数的二进制表示里的1的个数

    输入:5

    输出:[ 0,1, 1, 2, 1, 2 ]

    状态转移:

    f[i] = f[i>>1] + ( i mod 2 )

    动态规划去除重复计算

     

    例十 序列型动态规划

    题目描述:

    一排N栋房子,每栋要漆成K种颜色之一,相邻不能漆成同色,第i栋房子漆第j种颜色的花费是cost[i][j],问漆这些房子的最小花费?

    确定状态:

    设油漆前i栋房子并且房子i-1是颜色1,颜色2,...颜色K的最小花费分别为f[i][1],f[i][2],...,f[i][K]

    状态转移:

    f[i][1] = min{ f[i-1][2] + cost[i-1][1],f[i-1][3] + cost[i-1][1],...,f[i-1][K] + cost[i-1][1] }

    K个式子我们不能全写出来,写一个for循环,优化下:

    f[i][j] = mink!=j { f[i-1][k] } + cost[i-1][j]

    每次求一组元素中除了一个元素之外其他元素的最小值,求最小的两个值即可。

    假如最小值是f[i-1][a],次小值是f[i-1][b]

    对于j = 1,2,3,...,a-1,a+1,...,K   

    f[i][j] = f[i-1][a] + cost[i-1][j]

    f[i][a] = f[i-1][b] + cost[i-1][a]

     

    例十一 序列型动态规划

    题目描述:

    有一排N栋房子(0~N-1),房子i里有A[i]个金币,有个贼人想选择一些房子偷金币,他不能偷任何相邻两家的,请问这个贼人最多能偷多少金币?

    确定状态:

    第N-1栋房子,要么偷,要么不偷。不偷时问题变成了求前N-2栋房子最多能偷多少。

    设f[i][0]表示不偷房子 i-1 的前提下,前 i 栋房子中最多能偷多少金币

    设f[i][1]表示偷房子 i-1 的前提下,前 i 栋房子中最多能偷多少枚金币

    转移方程:

    f[i][0] = max { f[i-1][0],f[i-1][1] }

    f[i][1] = f[i-1][0] + A[i-1]

    发现不偷时 f[i][0] = f[i-1][1] 故存在重复,可以简化成以为:

    f[i] = max{ f[i-1] ,f[i-2] + A[i-1] }

    初始边界:

    f[0] = 0,f[1] = A[0], f[2] = max{ A[0],A[1] }

     

    例十二 例十升级

    题目描述:

    有一N栋房子(0~N-1),房子i里有A[i]个金币,有个贼人想选择一些房子偷金币,他不能偷任何相邻两家的,请问这个贼人最多能偷多少金币?

    确定状态:

    情况1:没偷房子0,就变成了1~N-1序列问题

    情况2:没偷房子N-1,就变成了0~N-2序列问题

    环形问题,针对性分析有什么情况,化作序列问题。

  • 相关阅读:
    解决方案-文件管理系统:百科
    计算机:轮询
    公司-科技-安全狗:百科
    职位-金融:CFA(特许金融分析师)
    un-解决方案-BPM:百科
    un-协议-LDAP:百科
    引擎-搜索引擎-Java:ElasticSearch
    云-京东云:目录
    计算机:E-Learning
    Runoob-JSP:JSP 国际化
  • 原文地址:https://www.cnblogs.com/thx2199/p/15168421.html
Copyright © 2020-2023  润新知