算法设计与分析课程复习笔记7——动态规划

算法设计与分析课程复习笔记7——动态规划

动态规划

  • 和分治法一样,是一种算法设计技术。
  • 子问题非独立。
  • 分治法通过递归方式解决性质相同的子问题,
    而动态规划每次解决一个子问题,并将结果存储在表格中。
  • 用于优化类问题。

算法:

  1. 描述最优解的结构特征
  2. 定义最优解决方案的递归形式
  3. 以自底向上的方式计算最优解决方案的值
  4. 从计算信息构造出最优解决方案

装配线排程

装配线排程
S 1 , 1 , S 1 , 2 , … … , S 1 , n ; S 2 , 1 , S 2 , 2 , … … , S 2 , n S_{1,1},S_{1,2},……,S_{1,n};S_{2,1},S_{2,2},……,S_{2,n} S1,1,S1,2,,S1,nS2,1,S2,2,,S2,n为两条装配线的工序站台
a 1 , 1 , a 1 , 2 , … … , a 1 , n ; a 2 , 1 , a 2 , 2 , … … , a 2 , n a_{1,1},a_{1,2},……,a_{1,n};a_{2,1},a_{2,2},……,a_{2,n} a1,1,a1,2,,a1,na2,1,a2,2,,a2,n为两条装配线的各站台工作时间
每条装配线的第j个站台的功能相同,但是效率不一致,即花费时间不同。
另外有上线时间 e 1 , e 2 e_1,e_2 e1,e2和下线时间 x 1 , x 2 x_1,x_2 x1,x2
以及从一条装配线变换到另一条装配线需要的时间 t 1 , 1 , t 1 , 2 , … … , t 1 , n − 1 ; t 2 , 1 , t 2 , 2 , … … , t 2 , n − 1 t_{1,1},t_{1,2},……,t_{1,n-1};t_{2,1},t_{2,2},……,t_{2,n-1} t1,1,t1,2,,t1,n1t2,1,t2,2,,t2,n1

问题:如何充分利用两条装配线,使得组装一辆汽车的时间最短?

解决方法:
1️⃣蛮力法
计算装配线排程所有可能的组合情况,比较并选择出最短时间的组合
2️⃣动态规划
【1】.构建最优解
考虑所有从起点到达 S 1 , j S_{1,j} S1,j可能途径
只有两种可能:
①从 S 1 , j − 1 S_{1,j-1} S1,j1直接到 S 1 , j S_{1,j} S1,j
②从 S 2 , j − 1 S_{2,j-1} S2,j1花费 t 2 , j − 1 t_{2,j-1} t2,j1时间转换到 S 1 , j S_{1,j} S1,j
构建最优解
如果到达 S 1 , j S_{1,j} S1,j的最快装配路线来自 S 1 , j − 1 S_{1,j-1} S1,j1那么必须是从装配线起点经过 S 1 , j − 1 S_{1,j-1} S1,j1的最快装配路线。 S 2 , j − 1 S_{2,j-1} S2,j1同理分析。

最优解的结构
寻求从起点到达 S 1 , j S_{1,j} S1,j最快装配路线,可分解为寻求从起点经过 S 1 , j − 1 S_{1,j-1} S1,j1 or S 2 , j − 1 S_{2,j-1} S2,j1 最快装配路线问题。
我们将这种具有分解递归特征的解的形式称为最优化结构特征
利用这种优化构造特征,从子问题的最优化解获得整个问题的最优化的解。

【2】.递归解
利用子问题的最优解,通过递归的方式求解原问题的最优解
f ∗ f* f为完成所有装配过程的最短时间。
f i [ j ] f_i[j] fi[j]表示从起点经过Si,j工序的最短时间.

f ∗ = m i n ( f 1 [ n ] + x 1 , f 2 [ n ] + x 2 ) f* = min (f_1[n] + x_1, f_2[n] + x_2) f=min(f1[n]+x1,f2[n]+x2)

j = 1 j=1 j=1
f 1 [ 1 ] = e 1 + a 1 , 1 f_1[1] = e_1 + a_{1,1} f1[1]=e1+a1,1
f 2 [ 1 ] = e 2 + a 2 , 1 f_2[1] = e_2 + a_{2,1} f2[1]=e2+a2,1

j ≥ 2 j≥2 j2
f 1 [ j ] = m i n ( f 1 [ j − 1 ] + a 1 , j , f 2 [ j − 1 ] + t 2 , j − 1 + a 1 , j ) f_1[j] = min(f_1[j - 1] + a_{1,j} ,f_2[j -1] + t_{2,j-1} + a_{1,j}) f1[j]=min(f1[j1]+a1,j,f2[j1]+t2,j1+a1,j)
f 2 [ j ] = m i n ( f 2 [ j − 1 ] + a 2 , j , f 1 [ j − 1 ] + t 1 , j − 1 + a 2 , j ) f_2[j] = min(f_2[j - 1] + a_{2,j} ,f_1[j -1] + t_{1,j-1} + a_{2,j}) f2[j]=min(f2[j1]+a2,j,f1[j1]+t1,j1+a2,j)

【3】.计算最优解
如果自顶向下求最优解:
自顶向下
那么将导致指数增长的计算时间。

所以我们选择按 j j j递增,即自底向上的方式求解。
自底向上
【4】.构建最优方案
最优排程序列
最优解
算法:
FastestWay(a,t,e,x,n)
  f 1 [ 1 ] ← e 1 + a 1 , 1 f_1[1] \leftarrow e_1+a_{1,1} f1[1]e1+a1,1
  f 2 [ 1 ] ← e 2 + a 2 , 1 f_2[1] \leftarrow e_2+a_{2,1} f2[1]e2+a2,1
 for j=2 to n
  do if f 1 [ j − 1 ] + a 1 , j f_1[j-1]+a_{1,j} f1[j1]+a1,j f 2 [ j − 1 ] + t 2 , j − 1 + a 1 , j f_2[j-1]+t_{2,j-1}+a_{1,j} f2[j1]+t2,j1+a1,j
   then f 1 [ j ] ← f 1 [ j − 1 ] + a 1 , j f_1[j] \leftarrow f_1[j-1]+a_{1,j} f1[j]f1[j1]+a1,j
      I 1 [ j ] ← 1 I_1[j] \leftarrow 1 I1[j]1
   else f 1 [ j ] ← f 2 [ j − 1 ] + t 2 , j − 1 + a 1 , j f_1[j] \leftarrow f_2[j-1]+t_{2,j-1}+a_{1,j} f1[j]f2[j1]+t2,j1+a1,j
      I 1 [ j ] ← 2 I_1[j] \leftarrow 2 I1[j]2
   if f 2 [ j − 1 ] + a 2 , j f_2[j-1]+a_{2,j} f2[j1]+a2,j f 1 [ j − 1 ] + t 1 , j − 1 + a 2 , j f_1[j-1]+t_{1,j-1}+a_{2,j} f1[j1]+t1,j1+a2,j
   then f 2 [ j ] ← f 2 [ j − 1 ] + a 2 , j f_2[j] \leftarrow f_2[j-1]+a_{2,j} f2[j]f2[j1]+a2,j
      I 1 [ j ] ← 2 I_1[j] \leftarrow 2 I1[j]2
   else f 2 [ j ] ← f 1 [ j − 1 ] + t 1 , j − 1 + a 2 , j f_2[j] \leftarrow f_1[j-1]+t_{1,j-1}+a_{2,j} f2[j]f1[j1]+t1,j1+a2,j
      I 1 [ j ] ← 1 I_1[j] \leftarrow 1 I1[j]1
 if f 1 [ n ] + x 1 ≤ f 2 [ n ] + x 2 f_1[n]+x_1 ≤ f_2[n] + x_2 f1[n]+x1f2[n]+x2
  then f ∗ = f 1 [ n ] + x 1 f* = f_1[n]+x_1 f=f1[n]+x1
     I ∗ = 1 I* = 1 I=1
  else f ∗ = f 2 [ n ] + x 2 f* = f_2[n]+x_2 f=f2[n]+x2
     I ∗ = 2 I* = 2 I=2

PrintStation(I,n)
 i ← I*
 print “line” i “,station” n
 for j ← n downto 2
  do i ← I i [ j ] I_i[j] Ii[j]
  print “line” i “,station” j-1

最优排程

矩阵链相乘

给定矩阵序列 A 1 , A 2 , … , A n A_1, A_2, …, A_n A1,A2,,An,求它们的积
C = A ∗ B C=A*B C=AB
c o l A = r o w B col_A=row_B colA=rowB
r o w C = r o w A row_C=row_A rowC=rowA
c o l C = c o l B col_C=col_B colC=colB
A 1 , A 2 , … , A n A_1, A_2, …, A_n A1,A2,,An
c o l i = r o w i + 1 col_i = row_{i+1} coli=rowi+1

矩阵链相乘的顺序极大的影响计算的代价

MatrixMultiply(A,B)
 if columns[A] ≠ rows[B]
  then error “incompatible dimensions”
  else for i ← 1 to rows[A]
     do for j ← 1 to columns[B]
      do C[i,j]=0
        for k ← 1 to columns[A]
         do C[i,j] ← C[i,j] + A[i,k]B[k.j]

A 1 ,     A 2 ,   … … ,   A n A_1,   A_2, ……,  A_n A1,  A2, , An
p 0 ∗ p 1 , p 1 ∗ p 2 , … … , p n − 1 ∗ p n p_0*p_1,p_1*p_2,……,p_{n-1}*p_n p0p1,p1p2,pn1pn

如何决定矩阵链相乘的顺序,即如何放置括号,使矩阵链相乘所需要的数量乘法的次数最小
1️⃣蛮力法
逐一比较
2️⃣动态规划
【1】.最优矩阵链相乘顺序结构
标记 A i … j A_{i…j} Aij= A i , A i + 1 , … … , A j A_i,A_{i+1},……,A_j Ai,Ai+1,,Aj= A i … k A k + 1 … j A_{i…k}A_{k+1…j} AikAk+1j

假设矩阵链 A i … j A_{i…j} Aij相乘的最优顺序在 A k A_k Ak A k + 1 A_{k+1} Ak+1分割

【2】.递归解
A i … j A_{i…j} Aij数量乘法的次数最小的运算顺序
利用m[i, j]标记 A i … j A_{i…j} Aij最小的数量乘法次数


i f   i = j if i=j if i=j
m [ i , j ] = 0 m[i,j]=0 m[i,j]=0
i f   i &lt; j if i&lt;j if i<j
m [ i , j ] = m i n i ≤ k ≤ j { m [ i , k ] + m [ k + 1 , j ] + p i − 1 p k p j } m[i,j]=min_{i≤k≤j}\{m[i,k]+m[k+1,j]+p_{i-1}p_kp_j\} m[i,j]=minikj{m[i,k]+m[k+1,j]+pi1pkpj}

动态规划的适用性

  • 最优解包含子问题的最优解
  • 递归算法一次又一次地重复同样的问题;只有Θ(n2)个子问题。

【3】.计算解
Matrix-Chain-Order(p)
 n ← length[p]-1;
 for i ← 1 to n
  m[i, i] ← 0;
 for I ← 2 to n
  for i ← 1 to n – l +1
   j ← i + l -1;
   m[i, j] ← ∞ \infty ;
   for k ← i to j -1
    q ← m[i, k] + m[k+1, j] + p I − 1 p k p j p_{I-1}p_kp_j pI1pkpj;
    if q < m[i, j]
     m[i,j] ← q;
     s[i, j] ← k;
 return m and s

矩阵链相乘
【4】.构造最优相乘顺序
s[i, j]:记录了 A i A i + 1 … A j A_i A_{i+1} … A_j AiAi+1Aj的最优分割顺序位置

Matrix-Chain-Multiply(A, s, i, j)
 if j > i
  X ← Matrix-Chain-Multiply(A, s, i, s[i,j]);
  Y ← Matrix-Chain-Multiply(A, s, s[i, j]+1, j);
  return Matrix-Multiply(X, Y);
 else return A i A_i Ai;

最长共同子序列LCS

Z =(B,C,A)是X,Y的一个共同子序列
X = (A,B,C,B,D,A,B)
Y = (B, D, C, A, B, A)
X,Y的最长共同子序列为 Z ′ Z&#x27; Z=(B, D, A, B)

解决方法
1️⃣蛮力法
穷举X的所有子序列,检查其是否在Y中出现,然后选出LCS
2️⃣动态规划
【1】.最优解结构
X = ( x 1 , x 2 , … … , x m ) X=(x_1,x_2,……,x_m) X=(x1,x2,xm)
Y = ( y 1 , y 2 , … … , y n ) Y=(y_1,y_2,……,y_n) Y=(y1,y2,yn)
L C S = Z = ( z 1 , z 2 , … … z k ) LCS=Z=(z_1,z_2,……z_k) LCS=Z=(z1,z2,zk)

如果 x m = y n x_m=y_n xm=yn,那么 z k = x m = y n z_k=x_m=y_n zk=xm=yn, Z k − 1 Z_{k-1} Zk1 X m − 1 X_{m-1} Xm1 Y n − 1 Y_{n-1} Yn1的LCS
如果 x m x_m xm y n y_n yn,那么 z k z_k zk x m x_m xm就意味着 Z Z Z X m − 1 X_{m-1} Xm1 Y Y Y的LCS
如果 x m x_m xm y n y_n yn,那么 z k z_k zk y n y_n yn就意味着 Z Z Z X X X Y n − 1 Y_{n-1} Yn1的LCS

【2】.递归解
C:X 和Y最长共同子序列的长度
c[i,j]: X i X_i Xi Y j Y_j Yj最长共同子序列的长度
问题的解即为c[m,n]

c [ i , j ] = { 0 ,   i f   i = 0   o r   j = 0 c [ i − 1 , j − 1 ] + 1 ,   i f   x i = y j , i , j &gt; 0 m a x ( c [ i , j − 1 ] , c [ i − 1 , j ] ) ,   i f   x i ≠ y j , i , j &gt; 0 c[i,j]=\left\{ \begin{aligned} 0, if i=0 or j=0\\ c[i-1,j-1]+1, if x_i=y_j,i,j&gt;0\\ max(c[i,j-1],c[i-1,j]), if x_i \neq y_j,i,j&gt;0 \end{aligned} \right. c[i,j]=0, if i=0 or j=0c[i1,j1]+1, if xi=yj,i,j>0max(c[i,j1],c[i1,j]), if xi̸=yj,i,j>0

【3】.计算解
LCS算法:
LCSlength(X,Y)
 m ← length(X)
 n ← length(Y)
 for i ← 1 to m
  c[i,0] ← 0
 for j ← 0 to n
  c[0,j] ← 0
 for i ← 1 to m
  for j ← 1 to n
   if x i x_i xi= y j y_j yj
    c[i,j] ← c[i-1,j-1] + 1
    b[i,j] ← “↖”
   else if c[i-1,j] ≥ c[i,j-1]
      c[i,j] ← c[i-1,j]
      b[i,j] ← “↑”
     else c[i,j] ← c[i,j-1]
       b[i,j] ← “←”
 return c and b

算法分析:其实就是简单的填表,一个格子的计算量为O(1),总共m*n个格子,所以总计算开销 O ( m n ) O(mn) O(mn)

【4】.构建最长共同子序列
最长共同子序列

参考:任课教师邱德红教授的课件

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值