[算法设计与分析-从入门到入土] 动态规划

算法设计与分析-从入门到入土 动态规划

知乎:https://www.zhihu.com/people/byzh_rc

CSDN:https://blog.csdn.net/qq_54636039

注:本文仅对所述内容做了框架性引导,具体细节可查询其余相关资料or源码

参考文章:各方资料

文章目录

  • [算法设计与分析-从入门到入土 动态规划](#[算法设计与分析-从入门到入土] 动态规划)
  • 动态规划
        • 1.最长公共子序列问题LCS
        • [2.全对最短路径问题(All-Pairs Shortest Path)](#2.全对最短路径问题(All-Pairs Shortest Path))
        • [3. 0/1背包问题Knapsack](#3. 0/1背包问题Knapsack)

动态规划

算法本身并非递归算法,但问题的解通常以递归的形式来表达

核心: 采用 自底向上 的求解思路, 空间换时间

通过存储子问题的解以避免重复计算,是这一强大算法范式的基础

该类问题的解通常可表示为递推关系式, 若直接求解会导致子问题被重复计算

e.g.斐波那契序列, 应该从下往上来算 f ( n ) f(n) f(n)

动态规划算法会为原问题所考虑的每个子问题实例都计算出最优解 ,阐释了算法设计中的一个重要原则------最优性原理:给定一个最优决策序列,其中的每个子序列本身也必须是最优决策序列

1.最长公共子序列问题LCS

给定两个字符串A和B,其长度分别为n和m,且字符均来自字母表Σ。要求确定同时是A和B的最长子序列的长度

字符串 A = a 1 a 2 ... a n A=a_1a_2...a_n A=a1a2...an的子序列是指形如 a i 1 a i 2 ... a i k a_{i1}a_{i2}...a_{ik} ai1ai2...aik的字符串,其中每个 i j i_j ij满足 1 ≤ i j ≤ n 1≤i_j≤n 1≤ij≤n,且下标严格递增: 1 ≤ i 1 < i 2 < . . . < i k ≤ n 1≤i_1 < i_2 < ... < i_k ≤ n 1≤i1<i2<...<ik≤n

例子:

A: ALGORITHM

B: PROGRAM

->

长度为1的子序列: A, G, R, M

长度为2的子序列: OR, RM, AM

长度为3的子序列: GRM, ORM

动态规划:

设 A = a 1 a 2 ... a n A = a_{1}a_{2} \dots a_{n} A=a1a2...an 与 B = b 1 b 2 ... b m B = b_{1}b_{2} \dots b_{m} B=b1b2...bm。

令 L i , j Li,j Li,j 表示 a 1 a 2 ... a i a_{1}a_{2} \dots a_{i} a1a2...ai 与 b 1 b 2 ... b j b_{1}b_{2} \dots b_{j} b1b2...bj 的最长公共子序列的长度,其中 0 ⩽ i ⩽ n 0 \leqslant i \leqslant n 0⩽i⩽n, 0 ⩽ j ⩽ m 0 \leqslant j \leqslant m 0⩽j⩽m

(从0开始, 也就是空字符串开始)

递推关系:

  • 若 a i = b j a_i = b_j ai=bj,则 L i , j = L i − 1 , j − 1 + 1 Li,j = Li-1,j-1 + 1 Li,j=Li−1,j−1+1
    (当前字符匹配,L左上角L加一)
  • 若 a i ≠ b j a_i \neq b_j ai=bj,则 L i , j = max ⁡ ( L i , j − 1 , L i − 1 , j ) Li,j = \max(Li,j-1, Li-1,j) Li,j=max(Li,j−1,Li−1,j)
    (当前字符不匹配,L为max(左边L, 上边L

用 ( n + 1 ) × ( m + 1 ) (n+1)×(m+1) (n+1)×(m+1) 的表格来计算 L i , j ( 0 ≤ i ≤ n , 0 ≤ j ≤ m ) Li,j \quad (0≤i≤n, 0≤j≤m) Li,j(0≤i≤n,0≤j≤m)

显然,若 i = 0 i=0 i=0 或 j = 0 j=0 j=0,则 L i , j = 0 Li,j=0 Li,j=0

例子:

A=zxyxyz

B=xyyzx

A(i) \ B(j) 0 x y y z x
0 0 0 0 0 0 0
z 0 0 0 0 1 1
x 0 1 1 1 1 2
y 0 1 2 2 2 2
x 0 1 2 2 2 3
y 0 1 2 3 3 3
z 0 1 2 3 4 4(结果长度)

第一行第一列都是0

时间复杂度: O ( n m ) O(nm) O(nm)

(需填充(n+1)×(m+1)个单元格,每个单元格计算耗时O(1))

空间复杂度: O ( m i n { m , n } ) O(min\{m,n\}) O(min{m,n})

(可优化为一维数组存储,仅保留前一行信息)

2.全对最短路径问题(All-Pairs Shortest Path)

G=(V,E) 为一个有向图,其中每条边 (i,j) 都有一个非负的长度 l\[i,j\]

(如果从顶点 i 到顶点 j 没有边,则 l\[i,j\] = \\infty )

目标: 找出每个顶点到所有其他顶点的距离

(从顶点 x 到顶点 y 距离 是指从 x y 的一条最短路径的长度)

假设 V = {1, 2, \\ldots, n} 。令 i j V 中两个不同的顶点

定义 d_{i,j}\^{k} 为从 i j 且不经过任何属于集合 {k+1, k+2, \\ldots, n} 中顶点的最短路径的长度

递推关系:
d i , j k = { l i , j if k = 0 min ⁡ { d i , j k − 1 , d i , k k − 1 + d k , j k − 1 } if 1 ≤ k ≤ n d_{i,j}^{k} = \begin{cases} li,j & \text{if } k = 0 \\ \min \left\{ d_{i,j}^{k-1},\ d_{i,k}^{k-1} + d_{k,j}^{k-1} \right\} & \text{if } 1 \leq k \leq n \end{cases} di,jk={li,jmin{di,jk−1, di,kk−1+dk,jk−1}if k=0if 1≤k≤n

  1. i = j i=j i=j时, d i , j k = 0 d_{i,j}^k=0 di,jk=0(顶点到自身的距离为0)
  2. i = k o r j = k i=k ~or~j=k i=k or j=k时, d i , j k = d i , j k − 1 d_{i,j}^k=d_{i,j}^{k-1} di,jk=di,jk−1(经过顶点k与否不影响路径)

动态规划(弗洛伊德算法):

使用 n+1 n \\times n 维矩阵 D_{0}, D_{1}, D_{2}, \\ldots, D_{n} 来计算受限最短路径的长度

初始化: 设置 D_{0}\[i,i\] = 0

  • 如果 i \\neq j (i,j) G 中的一条边,则 D_{0}\[i,j\] = l\[i,j\]
  • 否则 D_{0}\[i,j\] = \\infty

进行 n 次迭代,使得在第 k 次迭代之后, D_{k}\[i,j\] 包含从顶点 i 到顶点 j 且不经过任何编号大于 k 的顶点的最短路径长度值

例子:

D0: (k=0)

1 2 3
1 0 2 9
2 8 0 6
3 1 ∞ \infty ∞ 0

D1: (k=i=j=1)

1 2 3
1 0 2 9
2 8 0
3 1 0

D1:

( D 1 2 , 3 = m i n { D 0 2 , 3 , D 0 2 , 1 + D 0 1 , 3 } = 6 D_12,3=min\{D_02,3,D_02,1+D_01,3\}=6 D12,3=min{D02,3,D02,1+D01,3}=6)

( D 1 3 , 2 = m i n { D 0 3 , 2 , D 0 3 , 1 + D 0 1 , 2 } = 3 D_13,2=min\{D_03,2,D_03,1+D_01,2\}=3 D13,2=min{D03,2,D03,1+D01,2}=3)

1 2 3
1 0 2 9
2 8 0 6
3 1 3 0

D2: (k=i=j=2)

1 2 3
1 0 2
2 8 0 6
3 3 0

D2:

( D 2 1 , 3 = m i n { D 1 1 , 3 , D 1 1 , 2 + D 1 2 , 3 } = 8 D_21,3=min\{D_11,3,D_11,2+D_12,3\}=8 D21,3=min{D11,3,D11,2+D12,3}=8)

( D 2 3 , 1 = m i n { D 1 3 , 1 , D 1 3 , 2 + D 1 2 , 1 } = 1 D_23,1=min\{D_13,1,D_13,2+D_12,1\}=1 D23,1=min{D13,1,D13,2+D12,1}=1)

1 2 3
1 0 2 8
2 8 0 6
3 1 3 0

D3: (k=i=j=3)

1 2 3
1 0 8
2 0 6
3 1 3 0

D3:

( D 3 1 , 2 = m i n { D 2 1 , 2 , D 2 1 , 3 + D 2 3 , 2 } = 2 D_31,2=min\{D_21,2,D_21,3+D_23,2\}=2 D31,2=min{D21,2,D21,3+D23,2}=2)

( D 3 2 , 1 = m i n { D 2 2 , 1 , D 2 2 , 3 + D 2 3 , 1 } = 7 D_32,1=min\{D_22,1,D_22,3+D_23,1\}=7 D32,1=min{D22,1,D22,3+D23,1}=7)

1 2 3
1 0 2 8
2 7 0 6
3 1 3 0
3. 0/1背包问题Knapsack

设 U = { u 1 , u 2 , ... , u n } U = \{ u_{1}, u_{2}, \dots, u_{n} \} U={u1,u2,...,un} 为待装入容量为 C C C 的背包中的 n n n 个物品的集合

  • 对于 1 ≤ j ≤ n 1 \leq j \leq n 1≤j≤n,令 s j s_{j} sj 和 v j v_{j} vj 分别表示第 j j j 件物品的体积和价值
    (均为正整数)

目标:从 U U U 中选取若干物品装入背包,使得总体积不超过 C C C,且总价值最大

-> 用数学表达,即求一个向量 ( x 1 , x 2 , ... , x n ) ∈ { 0 , 1 } n (x_1, x_2, \dots, x_n) \in \{0, 1\}^n (x1,x2,...,xn)∈{0,1}n,使得:
最大化 ∑ j = 1 n v j x j 满足约束 ∑ j = 1 n s j x j ≤ C \text{最大化} \quad \sum_{j=1}^{n} v_{j} x_{j} \\ \text{满足约束} \quad \sum_{j=1}^{n} s_{j} x_{j} \leq C 最大化j=1∑nvjxj满足约束j=1∑nsjxj≤C

简言之,找到子集 S ⊆ U S \subseteq U S⊆U,使得 ∑ u i ∈ S v i \sum_{u_{i} \in S} v_{i} ∑ui∈Svi最大化,且 ∑ u i ∈ S s i ≤ C \sum_{u_{i} \in S} s_{i} \leq C ∑ui∈Ssi≤C

物品要么选要么不选,不能分割 -> 0/1背包问题

动态规划:

设 V i , j Vi, j Vi,j 表示使用前 i i i 个物品 { u 1 , u 2 , ... , u i } \{u_1, u_2, \dots, u_i\} {u1,u2,...,ui} 以最优方式填充大小为 j j j 的背包所能获得的最大价值( 0 ≤ i ≤ n , 0 ≤ j ≤ C 0 \leq i \leq n, 0 \leq j \leq C 0≤i≤n,0≤j≤C)

-> 最终要求解的值是 V n , C Vn, C Vn,C

  • 对于所有的 j j j, V 0 , j = 0 V0, j = 0 V0,j=0(没有物品时,任何容量背包的最大价值为0)
  • 对于所有的 i i i, V i , 0 = 0 Vi, 0 = 0 Vi,0=0(容量为0的背包无法放入任何物品,价值为0)

递推关系:
V i , j = { 0 if i = 0 or j = 0 V i − 1 , j if s i > j max ⁡ { V i − 1 , j , v i + V i − 1 , j − s i } if s i ≤ j Vi,j = \begin{cases} 0 & \text{if } i=0 \text{ or } j=0 \\ Vi-1,j & \text{if } s_i>j \\ \max \left\{ Vi-1,j,v_i+Vi-1,j-s_i \right\} & \text{if } s_i \leq j \end{cases} Vi,j=⎩ ⎨ ⎧0Vi−1,jmax{Vi−1,j,vi+Vi−1,j−si}if i=0 or j=0if si>jif si≤j

时间复杂度: Θ ( n C ) \Theta(nC) Θ(nC)

空间复杂度: Θ ( C ) \Theta(C) Θ(C)

例子:

v i v_i vi s i s_i si KaTeX parse error: Undefined control sequence: \textbackslash at position 3: i \̲t̲e̲x̲t̲b̲a̲c̲k̲s̲l̲a̲s̲h̲ ̲j 0 1 2 3 4 5 6 7 8 9
0 0 0 0 0 0 0 0 0 0 0
3 2 1 0 0 3 3 3 3 3 3 3 3
4 3 2 0 0 3 4 4 7 7 7 7 7
5 4 3 0 0 3 4 5 7 8 9 9 12
7 5 4 0 0 3 4 5 7 8 10 11 14(结果)
相关推荐
通信小呆呆4 小时前
当算法有了“五感”:多模态数据融合如何向人体感官协同学习?
人工智能·学习·算法·机器学习·机器人
benben0444 小时前
强化学习之DQN算法族(基于gymnasium开发)
算法
何以解忧,唯有..6 小时前
Go语言循环语句详解:for、range与循环控制
开发语言·算法·golang
想吃火锅10056 小时前
【leetcode】88.合并两个有序数组js
算法
生成论实验室7 小时前
机器人:一个自主运动的系统
人工智能·算法·语言模型·机器人·自动驾驶·agi·安全架构
Qres8217 小时前
算法复键——树状数组
数据结构·算法
H178535090967 小时前
SolidWorks第四部分_直接实体建模特征9_替换面原理
线性代数·算法·机器学习·3d建模·solidworks
不会就选b7 小时前
算法日常・每日刷题--<二分查找>3
算法
绿算技术8 小时前
Mooncake 与绿算ForinnBase GroundPool如何联手打破推理僵局?
科技·算法·架构