一般步骤
- 问题分析 给出问题表示,明确原始问题
- 推导递推式 分析最优结构,构造递推公式
- 自底向上计算 确定计算顺序,依此求解问题
- 最优方案追踪 记录决策方法,输出最优方案
适合的问题类型:问题的解与子问题的解存在一定的递推关系,问题的最优解由相关子问题最优解组合而成,子问题可以独立求解。
例题分析
-
不同路径来自力扣
-
题意:在如图一个网格上机器人每次只能向右或向下移动一步移动到右下角需要多少步?
-
分析:有一种想法是利用图算法建立一个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[i−1][j−1]
-
此外,第一行第一列的各块砖都只有一条路径。因此有边界条件:
-
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))
-
-
最大子列和具体题目可以参考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[i−1]+X[i]X[i]Sum[i−1]>0Sum[i−1]<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]))
- 钢条切割问题
- 等待更新