动态规划---初了解

动态规划基本思想:

       将待求解的问题分解成若干个相互联系的子问题,先求解子问题,然后从这些子问题的解得到原问题的解;对于重复出现的子问题,只在第一次遇到的时候对它进行求解,并把答案保存起来,让以后再次遇到时直接引用答案,不必重新求解。

动态规划程序设计往往是针对一种最优化问题,由于各种问题的性质不同,确定最优解的条件也互不相同,因而动态规划的设计方法对不同的问题,有各具特色的解题方法,而不存在一种万能的动态规划算法可以解决各类最优化问题。

下面用一个例子来体现动态规划思想:

在上面的数字三角形中寻找一条从顶部到底边的路径,使得路径上所经过的数字之和最大。路径上的每一步都只能往左下或右下走。只需要求出这个最大和即可,不必给出具体路径。

看到这个题,我认为比较容易理解的方法是递归,就首先拿python代码实现递归:

L = [[7],
     [3, 8],
     [8, 1, 0],
     [2, 7, 4, 4],
     [4, 5, 2, 6, 5]]
length = len(L) - 1
def maxSum(r, c):
    '''
    功能:从二维列表L 数字三角形中找出一条路径,
          使得路径上的所有数字之和最大
    参数:r: 行
          c: 列
    返回:最大的数字之和
    '''
    if r == length:
        return L[r][c]
    x = maxSum(r + 1, c)
    y = maxSum(r + 1, c + 1)
    return max(x, y) + L[r][c]


print(maxSum(0,0))

以上代码输出结果 30。但是以上代码有大量的重复计算,经过同一个数的每条路径都会重新计算一遍,浪费了大量的时间。时间复杂度达到了2的n次方,很浪费时间。接下来进行改进代码,如果我们把之前计算过的数据进行存储,然后下一次不再进行计算,而直接使用,就会免去重复计算,节省好多时间。三角形总共有n(n+1)/2个数字,时间复杂度为n方。

但是这样我们还是使用了递归(只是记忆的),因为递归需要消耗大量的内存空间,所以我们还需要改进代码,不使用递归来完成。如果我们从最后一行往前推,倒数第二行的数加上倒数第一行的数即:倒数第二行的2加最后一行的4和5取最大值 max((2+4),(2+5)) =7,   max((7+5),(7+2))=12,... ...以此类推把倒数第二行填上这些数保存,即左图。前三行一样,相加取最大值并保存(右图),最后得出的第一行的第一个数便是咱们上个程序得出的结果。

                                 

将以上的过程使用Python代码实现,这便是使用动态规划的思想实现的代码,分解成小问题,解决小问题,用小问题来进一步解决大问题

import numpy as np
L = [[7],
     [3, 8],
     [8, 1, 0],
     [2, 7, 4, 4],
     [4, 5, 2, 6, 5]]
length = len(L) - 1
# 此处使用了numpy的创建数组函数,以便存储之后求的值
maxS = np.zeros((length + 1, length + 1))
def maxSum():
    for i in range(length):
        maxS[length][i] = L[length][i]
    for i in range(length - 1, -1, -1):
        for j in range(i + 1):
            maxS[i][j] = max(maxS[i + 1][j], maxS[i + 1][j + 1]) + L[i][j]
    # 这里返回的值便是最后算出的结果
    return maxS[0][0]
print(maxSum())

代码还可以继续进行优化,不必使用二维数组,使用一维的足够了。如下图所示递推,得到的第一个数便是所要求的数。

虽然空间上得到了优化,但是时间复杂度不变。

             

简化后的代码如下:

def maxSum():
    maxS = L[length]
    for i in range(length - 1, -1, -1):
        for j in range(i + 1):
            maxS[j] = max(maxS[j], maxS[j + 1]) + L[i][j]
    return maxS[0]

这个动态规划的例子到这里已经完成了。做完这个例子,基本了解了动态规划的思想,但是涉及动态规划的问题很多,每种问题的解决办法不一样,还需要具体问题具体分析,我们也可以通过对若干有代表性的问题的动态规划算法进行分析、讨论,逐渐学会并掌握这一设计方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CharlesWu123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值