算法54---动态规划

一、啥问题可以用动态规划来解决【采用空间来存储重复计算的结构】

  1. 最优子结构:就是原问题可以分为多个子问题。
  2. 重复子问题:子问题在计算过程中是重复计算的。

举例子:斐波那契问题:F(n) = F(n-1) + F (n-2)

F(n)分为两个子问题:F(n-1)和F(n-2),

而F(n-1)和F(n-2)重复计算了F(n-2)部分,所以这两个问题就是重复子问题

重复子问题可以用空间来存储计算过的值,当在计算过程中重复使用的时候就可以在存储表中取值。

二、例子解析:

子问题:dp[i][j] 可分为 dp[i][j-1] 和 dp[i-1][j]两个子问题。

状态方程:dp[i][j] = min(dp[i][j-1],dp[i-1][j]) + grid[i][j]

  • 龙下城游戏dp[i[[j]:如果骑士要走上位置(i,j),并且从该位置选一条最优的路径,最后走到右下角,骑士起码应具备的血量。最终结果为dp[0][0]。

子问题:dp[i][j+1]、dp[i+1][j]

状态方程:

如果骑士向右选择,dp[i][j]_1  = max{ dp[i][j+1] - map[i][j] , 1}     

如果骑士向下选择,dp[i][j]_2  = max{ dp[i+1][j] - map[i][j] , 1}     

dp[i][j] = min{ dp[i][j]_1, dp[i][j]_2}

子问题:邻近的两个:dp[i-1][j-1]、dp[i-1][j]

状态方程:dp[i][j] = min(dp[i-1][j-1],dp[i-1][j]) + triangle[i][j]

子问题:dp[i-1][j-1]、dp[i-1][j+1]、dp[i-1][j]

状态方程:dp[i][j] = min(dp[i-1][j-1], dp[i-1][j+1], dp[i-1][j] ) + A[i][j]

 

子问题:dp[i-1][j]、dp[i][j-1]

状态方程:dp[i][j] = dp[i-1][j] + dp[i][j-1]

状态方程:dp【i】 = min(dp[i-1] , dp[i-2] + nums[i] )

状态方程:dp[0] = 0,dp[1] = cost[0]

dp[i] = min(dp[i-1],dp[i-2]) + cost[i]

  • 石子游戏dp[i][j]表示:表示在piles中下标 i 至下标 j 之间的玩家1 所拿石子总数和 玩家2所拿石子总数之差。dp[i][j] > 0 表明玩家1赢,输出True

状态方程:dp[ i ][ j ] = piles[ i ](初始)

dp[ i ][ j ] = max( piles[ i ] - dp[ i+1 ][ j ], piles[ j ] - dp[ i ][ j-1 ])

子问题:dp[i][j] 可分为 dp [j-arr[i]]dp [i-1][j]两个子问题。

状态方程:dp [i][j] = min( dp [j-arr[i]] +1,dp [i-1][j]

子问题:dp[i][j] 可分为 dp [j-arr[i]]dp [i-1][j]两个子问题。

状态方程:dp[i][j] = dp[i][j-arr[i]] + dp[i-1][j]

  • 最长公共子序列:c[i][j]表示(x1,x2....xi) 和 (y1,y2...yj) 的最长公共子序列的长度

原问题:c[i][j]

子问题:当两个序列的最后一个元素相等,即Xi =Yj,则❶c[i-1][j-1]   

    否则当 Xi ≠Yj, ❷c[i][j-1]   ❸c[i-1][j]

状态方程:

原问题:给定一个数列,长度为N,设 dp[j] 为:以数列中第 j 项结尾的最长递增子序列的长度,求max(dp).

子问题:对 dp[j] 来讲,dp[0]……dp[j-1] 都是 dp[j] 的子问题

状态方法:dp(j) = { max(dp(i)) + 1, i<j且L[i]<L[j] }

  • 最长公共子串dp[i][j]用来记录具有这样特点的子串——结尾同时也为子串x1x2⋯xi与y1y2⋯yj的结尾的长度。

子问题:c[i-1][j-1]

 

状态方法:

状态方程:如果s1[i] == s2[j]: dp[i][j] = dp[i-1][j-1]

否则:dp]i][j] =  dp[i][j] = min(dp[i][j-1] +ord(s2[j-1]),dp[i-1][j] + ord(s1[i-1]),dp[i-1][j-1] + ord(s1[i-1])+ord(s2[j-1]))

  • 最小编辑代价dp[i][j]表示str1[0......i-1]编辑成str2[0......j-1]的最小编辑代价。

子问题:dp[i][j-1]、dp[i-1][j]、dp[i-1][j-1]

状态方法:dp[i][j] = min( dp[i][j-1]+icdc+dp[i-1][j]dp[i-1][j-1] + rc 【如果str1[i-1]==str2[j-1],rc = rc,否则,rc = 0】)

  • 交错字符串dp[i][j] 代表是s1的前i个字符与s3中匹配,s2中前j个字符与s3中匹配.

子问题:dp[i-1][j]、dp[i][j-1]

状态方法:dp[i][j] = (dp[i-1][j] == True and s1[i-1] == s3[i+j-1]) or (dp[i][j-1] ==True and s2[j-1] == s3[i+j-1])

状态转移方程:F(n) = min{ F(n-ai) + 1 } 其中ai为小于等于n的完全平方数

状态方程:dp[i] = dp[i-1] + fi,

  记 f( n )为 [ 0, 10^n )范围内满足条件的数值个数,记 g( k ) 为 k位数中满足条件的数值个数, 则 f(n) = g(1) + g(2) + g(3) + ... +g(n) = f (n - 1) + g (n),

我们看abcd这个字符串,

以a为结尾的子字符串为a,dp[0] = 1

以b为结尾的子字符串为b,ab 。dp[1] = 2

以c为结尾的子字符串为c,bc,abc。dp[2] = 3

以d结尾的子字符串有abcd, bcd, cd, d,故 i = 3,dp[3] = 4。

结果为:1+2+3+4 = 10

题目可以转换为分别求出以每个字符(a-z为结束字符的最长连续字符串就行了,我们用一个数组res记录下来,最后在求出数组res的所有数字之和就是结果。

  •  n个学生成绩排名,a>b>c……,a>b=c,有多少种排名。dp[j] = (j+1) * (dp[j-1] + dp[j])

 

posted on 2018-11-17 16:03  吱吱了了  阅读(327)  评论(0编辑  收藏  举报

导航