动态规划

来源:互联网 发布:wows更新数据出错 编辑:程序博客网 时间:2024/06/03 09:56

什么是动态规划

个人理解是:将问题分解成相似的子过程或步骤,将大事化小,逐步求解的方式。

动态规划三个要素


  1. 最优子状态:将复杂问题简单化的过程,建模的第一步。比如计算N的斐波那契数值。可以先寻找N和N-1的关系:F(N)=F(N-1)+F(N-2); 这就最优子状态,将“大”问题往小了化解,个人认为这一步是最难的。
  2. 边界:问题最终可以通过动态规划来计算的关键,是最优子状态的最简单情况。比如斐波那契数列中的F(0)=1和F(1)=1;就是该问题的边界,是后续推导的起点。
  3. 状态转移公式:就是对上述两点的数学建模。斐波那契数列的公式就是他的状态转移公式

N = 0: F(0)=1
N = 1: F(1)=1
N > 1: F(N) = F(N-1) + F(N-2)

例子

举个今天从微信公众号“算法和数据结构”上的问题,我用Javascript实现了递归算法:

    /**  问题:假设有N个金矿,M个矿工,每个金矿的产量为g[i],需要人工p[i],每个金矿必须足员才能开功,求最大开采量及开采的矿  动态规划法:  假设最大开采量公式为F(N,M);  最优子结构:找到N个矿和N-1个矿之间的关系      假设开采第N个矿,则最大开采量应该是Max(F(N-1,M-p[n])+g[n],F(N-1,M));      假设不开采第N个矿,则最大开采量应该是F(N-1,M);  边界:      当N=1时,如果p[0] > M,则最大开采量为g[0];               如果p[0] < M,则最大开采量为0;  状态转换公式:      p[n] > M : F(N-1,M);      p[n] < M : Max(F(N-1,M-p[n])+g[n],F(N-1,M));**/    function findWayToDig(w,ar){    if(ar.length<1){        console.log("The init array is empty!!!");    }    if(ar.length==1){        if(ar[0].ppl > w ){            return 0;        }else{            return ar[0].amt;        }    }    var amt = ar[0].amt;    var ppl = ar[0].ppl;    var next = ar.slice(1);    if(ppl > w){        return findWayToDig(w,next);    }else{        return Math.max(amt + findWayToDig(w-ppl,next),findWayToDig(w,next));    }}(function(){    var ar =[{amt:500,ppl:5},             {amt:200,ppl:3},{             amt:300,ppl:4             },             {amt:350,ppl:3},             {amt:400,ppl:5}];    console.log(findWayToDig(10,ar));            })();
  • 首先上述方法有优化空间,可以增加一个临时对象保存历史计算结果findWayToDig(w,next)。
  • 其次还可以使用迭代法(正向推导)来实现,这部分有空补上。
原创粉丝点击