ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

动态规划学习

2021-11-04 22:59:17  阅读:150  来源: 互联网

标签:return lcs str2 str1 学习 range 动态 规划 dp


动态规划

动态规划问题简称为DP问题(dynamic problem)

  1. 规模是否可缩小
  2. 用函数思想构造一个状态表达式(黑盒思路)
  3. 构造状态转移
  4. 优化(memorization/tabulation)

e.g. Longest Common Subsequence(LCS)

  1. 规模是否可缩小
  2. 用函数思想构造一个状态表达式(黑盒思路)
    • lcs(str1, str2, m, n)
  3. 构造状态转移
    • 1+lcs(m-1, n-1)
    • max(lcs(m-1, n), lcs(m, n-1))
  4. 优化(memorization/tabulation)
    • overlapping

在这里插入图片描述

1 递归树 Recursive Tree

def lcs(str1, str2, m, n):
    if m == 0 or n == 0:
        return 0
    if str1[m-1] == str2[n-1]:
        case1 = 1 + lcs(str1, str2, m-1, n-1)
        return case1
    else:
        case2 = max(lcs(str1, str2, m-1, n), lcs(str1, str2, m, n-1))
        return case2

In:

str1 = 'abcdef'
str2 = 'afbce'
m = len(str1)
n = len(str2)
res = lcs(str1, str2, m, n)
print(res)

Out:

4

在这里插入图片描述

存在overlapping的问题

2 memoization

改进(自上而下):

def lcs(str1, str2, m, n):
    #m, n 规模的问题对应的矩阵坐标为m-1, n-1
    if m == 0 or n == 0:
        dp[m][n] = 0
        return 0
    if dp[m][n] != -1:
        return dp[m][n]
    if str1[m-1] == str2[n-1]:
        case1 = 1 + lcs(str1, str2, m-1, n-1)
        dp[m][n] = case1
        return case1
    else:
        case2 = max(lcs(str1, str2, m-1, n), lcs(str1, str2, m, n-1))
        dp[m][n] = case2
        return case2

In:

str1 = 'bd'
str2 = 'abcd'
m = len(str1)
n = len(str2)
dp = [[-1] * (n+1) for _ in range(m+1)]
res = lcs(str1, str2, m, n)
print(res)
print(dp)

Out:

2
[[-1, 0, -1, 0, -1], [-1, -1, 1, 1, -1], [-1, -1, -1, -1, 2]]

在这里插入图片描述

3 tabulation

改进(自下而上):

def lcs(str1, str2, m, n):
    dp = [[0] * (n+1) for _ in range(m+1)]
    for i in range(1, m+1):
        for j in range(1, n+1):
            left = dp[i][j-1]
            up = dp[i-1][j]
            left_up = dp[i-1][j-1]
            if str1[i-1] == str2[j-1]:
                dp[i][j] = left_up + 1
            else:
                dp[i][j] = max(left, up)
    #print(dp)
    return dp[m][n]

在这里插入图片描述

4 空间优化

4.1 只用两行矩阵

def lcs(str1, str2, m, n):
    dp = [[0] * (n+1) for _ in range(2)]
    #这里发生了变化,只需要两行来推断下面的表格
    for i in range(1, m+1):
        for j in range(1, n+1):
            #代码中的dp[0]代表前一行
            #代码中的dp[1]代表当前行
            left = dp[1][j-1]
            up = dp[0][j]
            left_up = dp[0][j-1]
            if str1[i-1] == str2[j-1]:
                dp[1][j] = left_up + 1
            else:
                dp[1][j] = max(left, up)
        #处理完一行,把当前行的值覆盖前一行
        for k in range(1, n+1):
            dp[0][k] = dp[1][k]
    #print(dp)
    return dp[m][n]

5 小结

tabulationmemoization
状态转移不好想利用递归的思想容易想
代码需要考虑矩阵的位置关系,
不好写
容易编写
速度直接通过访问前一个状态的结果计算下一个状态
速度快
多层递归,由于递归的层数在系统中是有限制的,所以有时候会慢,甚至达到限制
表内数据每一个元素都要填充数据只有需要的位置才会被填充上数据

下一个状态
速度快 | 多层递归,由于递归的层数在系统中是有限制的,所以有时候会慢,甚至达到限制 |
| 表内数据 | 每一个元素都要填充数据 | 只有需要的位置才会被填充上数据 |

标签:return,lcs,str2,str1,学习,range,动态,规划,dp
来源: https://blog.csdn.net/weixin_42764266/article/details/121153410

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有