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

动态规划

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),n2 p(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})的最优分割点k
integer N,I,J,K,T,R(N+1),D(N,N)
for I<- 1 to N do 
    D(I,I)=0
repeat
for 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
    repeat
repeat
end 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(')')
        }
endcase
end P             

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

最短路径

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

主要采用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
    repeat
repeat
end 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
    repeat
repeat
end MinPath

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值