动态规划

本文介绍了动态规划的基本概念,包括最优子状态、边界与状态转移公式,并通过一个具体的矿工开采问题展示了如何应用动态规划解决问题。

什么是动态规划

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

动态规划三个要素


  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)。
  • 其次还可以使用迭代法(正向推导)来实现,这部分有空补上。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值