动态规划求解问题总结

一般步骤
  • 问题分析 给出问题表示,明确原始问题
  • 推导递推式 分析最优结构,构造递推公式
  • 自底向上计算 确定计算顺序,依此求解问题
  • 最优方案追踪 记录决策方法,输出最优方案

适合的问题类型:问题的解与子问题的解存在一定的递推关系,问题的最优解由相关子问题最优解组合而成,子问题可以独立求解。

例题分析

  1. 不同路径来自力扣

    • 题意:在如图一个网格上机器人每次只能向右或向下移动一步移动到右下角需要多少步?

    • avatar

    • 分析:有一种想法是利用图算法建立一个21*21的有向图,每个节点都只与他下边和右边的结点相连,然后利用深度优先或广度优先遍历一遍,但是时空复杂度较大。

    • 我们先从右下角那块开始看,要到达右下角那块砖,只有两条路一个是从上边一个是从下边,所以到达最后一块砖的路径数显然等于到上面那块砖的路径数再加上到左边那块砖的路径数。假设行数和列数分别由 i i i j j j表示,那么可以用 R [ i , j ] R[i,j] R[i,j]来表示从左上角到第 i i i行第 j j j列的路径,具有下列递推关系:

    • R [ i , j ] = R [ i − 1 ] [ j − 1 ] R[i,j]=R[i-1][j-1] R[i,j]=R[i1][j1]

    • 此外,第一行第一列的各块砖都只有一条路径。因此有边界条件:

    • R [ i , 0 ] = R [ 0 , j ] = 1 R[i,0]=R[0,j]=1 R[i,0]=R[0,j]=1

    • 下面看详细代码

    def path(m,n):# m为行数n为列数
        R=[[1 for i in range(n)] for j in range(m)]#初始化列表
        for i in range(1,m):
            for j in range(1,n):
         		R[i][j]=R[i-1][j]+R[i][j-1]#迭代计算每个结点的路径
        return R[-1][-1]
    if __name__=="__main__":
        print(path(3,7))
    
  2. 最大子列和具体题目可以参考PTA

    • 对于一个数列 X = [ − 2 , 11 , − 4 , 13 , − 5 , − 2 ] X=[-2,11,-4,13,-5,-2] X=[2,11,4,13,5,2]来说
    • 可以直接暴力求解,代码如下
def MaxSumofSubquence(X):
    Max=0
    start=0
    end=0
    tempSum=0
    for i in range(len(X)):
        tempSum=X[i]
        if tempSum>Max:
            Max=tempSum
            start=i
            end=i
        for j in range(i+1,len(X)):
            tempSum+=X[j]
            if tempSum>Max:
                Max=tempSum
                end=j
    print("最大子列和%d,起点%的,终点%d"%(Max,start,end))
  • 这个时间复杂度是 O ( n 2 ) O(n^2) O(n2)代价较大

  • 下面用动态的思想来分析求解:

  • 分析:如果必须包含数组最后一个元素在子序列中,会有两种情况(1)包含倒数第二个子序列的子序列和为非负数(2)包含倒数第二个子序列的子序列和为负数。用 S u m [ i ] Sum[i] Sum[i]来表示必须包含第 i i i个元素的子列和。显然依照以上两种情况有以下递推式:

  • S u m [ i ] = { S u m [ i − 1 ] + X [ i ] S u m [ i − 1 ] > 0 X [ i ] S u m [ i − 1 ] < 0 Sum[i]=\left\{ \begin{aligned} Sum[i-1]+X[i] & & Sum[i-1]>0\\ X[i] & & Sum[i-1]<0 \\ \end{aligned} \right. Sum[i]={Sum[i1]+X[i]X[i]Sum[i1]>0Sum[i1]<0

  • 边界:

  • S u m [ 0 ] = X [ 0 ] Sum[0]=X[0] Sum[0]=X[0]

  • def MaxSumofSubquence(X):
        Sum=[0]*len(X)
        Sum[0]=X[0]
        start=0
        end=0
        Max=X[0]
        for i in range(1,len(X)):
            if Sum[i-1]>0:
                Sum[i]=Sum[i-1]+X[i]
                if Max<Sum[i]:
                    Max=Sum[i]
                    end=i
            else:
                Sum[i]=X[i]
                if Max<Sum[i]:
                    Max=Sum[i]
                    start=i
                    end=i
        print("子序列为")
        for i in range(start,end+1):
            print(X[i],end=' ')
        print("和为"+str(Sum[end]))
    
  1. 钢条切割问题
    • 等待更新
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值