【算法学习】动态规划 Dynamic Programming

来源:互联网 发布:域名如何别名解析 编辑:程序博客网 时间:2024/05/16 04:13

动态规划

Dynamic Programming

  • 动态规划
    • 矩阵连乘
    • 最短路径

动态规划是用于解决多阶段决策最优化问题的算法设计方法。该术语是1957年Richard Bellman在描述一类最优控制问题时提出的。该术语描述的是问题特征,而非方法特征。该类问题的特征是,它的活动过程可以分为有序的若干阶段,而且在任一阶段i,过程在阶段i以后的行为仅依赖与阶段i的过程状态,与阶段i以前过程如何到达这种状态无关(这儿是不是有点类似于马尔科夫过程)。它满足所谓的最优性原理(和贪心法类似)。最优性原理指的是,过程的最优决策序列具有如下性质:无论过程的初始状态和初始决策时什么,其余的决策必须相对于初始决策产生的状态构成一个最优决策序列。

动态决策时建立在最优性原理基础上的枚举法,该问题的解可被看作k个阶段决策的结果,其子问题解相应地可被看作j(1jk)个阶段决策的结果,其中j+1个阶段子问题的最优解是由j个阶段子问题的最优解生成的,由此就可以得到子问题间的递推关系式,从而解出整个问题的最优解。所以解决问题的关键在于获取各阶段间的递推关系式。

下面来举几个具体的例子:
- 矩阵连乘
- 求最小路径

矩阵连乘

考虑n个矩阵连乘积问题:
M1M2...Mn=?

任意A,B两个矩阵相乘,必须满足A 的列数等于B的行数。
设A的大小为p×q,B的大小为q×r,那么求AB矩阵乘积的运算量为pqr。(包括pqr次乘法,pqr次加法,pqr次赋值。)

事实上不同的矩阵结合方式会带来不同的运算量,怎么利用动态规划求使得运算量最小的矩阵连乘方案呢。

先来估算结合方式数目,规模为n的矩阵连乘结合方式数目为p(n)
p(1)=1
p(n)=p(1)p(n1)+p(2)p(n2)++p(n1)p(1),n2p(n)=12Cn12(n1),p(n)2n2这就是Catalan数。

用动态规划法求解该问题,假设最优结合法最后一次乘法是M1,iMi+1,n,即M1,n=M1,i+Mi+1,n,且M1,iMi+1,n各自的结合法也是最优的,满足最优性原理。设mi,jMi,j所需要的最小运算量,则
mi,i=0,1in
mi,j=minik<j{mi,k+mk+1,j+ri1rkrj},1i<jn
可以通过一个n阶方阵来表示出各个最小运算量mi,j及分割矩阵Mi,j的最佳分割点k。

伪代码:

procedure MatMultiply(N,R,D)//N是矩阵连乘的个数//R(N+1)存放N个矩阵的行列树//DN阶方阵,D(i,j)=mij(i<j)//D(j,i)=(M^{i,j} = M^{i,k}M^{k+1,j})的最优分割点kinteger N,I,J,K,T,R(N+1),D(N,N)for I<- 1 to N do     D(I,I)=0repeatfor I<- 1 to N-1 do         for J<- 1 to N-1 do        D(J,J+I) = MAXINT        for K<- 0 to I-1            T = D(J,J+K)+D(J+K+1,J+I)+R(J-1)R(J+K)R(J+I)            if T<D(J,J+I)                then D(J,J+I)<- T;D(J+I,J)<- J+K            endif        repeat    repeatrepeatend MatMultiply               

D(j,i)(i<j)确定N个矩阵的最佳结合方式,这由一个递归过程来完成。

procedure P(I,J)//过程P给出矩阵M^{I},...,M^{J}连乘的最佳结合方式,//也就是在M^{I},...,M^{J}中添加表示结合的括弧case    :I=J:write('(M^{I})')    :I+1=J:write('(M^{I}M^{J})')    :else:        {        K<- D(J,I)        write('(')        call P(I,K)        call P(K+1,J)        write(')')        }endcaseend P             

算法复杂度主要在计算MatMultiply(n3),而添加括弧只用了线性复杂度的时间。

最短路径

图G=(V,E,W)是一个带边权的有向图,边权可以为负,但不存在负回路,给定图中节点i,jij最小路径(长度及道路)。

主要采用Floyd-Warshall算法。
在这里直接给出伪代码:

procedure initial(n,w,d,Q)//initializing//n节点数//w边权//d(i,j)最小路径长度//Q(i,j):j的直接前驱(i-j路径上位于j前一个的点)for i<-1 to n do     for j<-1 to n do         d(i,j)<- w((i,j))        Q(i,j)<-i    repeatrepeatend initial
procedure MinPath(d,Q)for k<- 1 to n do     for i<-1 to n do         for j<-1 to n do            if d(i,k)+d(k,j)<d(i,j)                then d(i,j)<-d(i,k)+d(k,j)                Q(i,j)<-Q(k,j)            endif        repeat    repeatrepeatend MinPath

来自北京大学杨老师的算法设计与分析课程笔记整理。