算法之动态规划

1 篇文章 0 订阅
1 篇文章 0 订阅
何为动态规划?

动态规划算法是通过拆分问题,定义问题状态和状态之间的关系,使得问题能够以递推的方式去解决。“大而化小,小而化无”。

什么时候用动态规划?

能采用动态规划求解的问题的一般要具有3个性质:

(1)最优化原理:假设问题的最优解所包括的子问题的解也是最优的,就称该问题具有最优子结构,即满足最优化原理。

(2)无后效性:即某阶段状态一旦确定。就不受这个状态以后决策的影响。也就是说,某状态以后的过程不会影响曾经的状态。仅仅与当前状态有关;

(3)有重叠子问题:即子问题之间是不独立的,一个子问题在下一阶段决策中可能被多次使用到(该性质并非动态规划适用的必要条件,可是假设没有这条性质。动态规划算法同其它算法相比就不具备优势)。

怎么使用动态规划?
  • 利用动态规划思想从上往下思考问题:将多阶段问题转变成更小的多阶段问题(状态转移方程)

  • 分解至最小的单阶段问题(可直接解决问题)。

  • 利用循环从下往上解决问题。

下面是一道简单的动态规划题,通过这道题讲解,了解如何使用动态规划。

阶梯问题

有N阶台阶,每一步可以走1步台阶或者2步台阶,求出走到第N阶台阶的方法数。
  • 多阶段问题转变成更小的多阶段问题

    假设我们现在还有最后一步要走,可能的情况有哪些?

    1)我们站在第N-1级上,一步1级后到达顶端;

    2)我们站在第N-2级上,一步2级后到达顶端;

    所以,最后一步可以走1级或者2级,不外乎两种情况。因此有状态转移方程:

    f(N)=f(N-1)+f(N-2)
    
  • 可直接解决问题

    f(1)=1
    f(2)=2
    
  • 下往上解决问题

    f(1)=1
    f(2)=2
    f(3)=f(2)+f(1)
    ...
    ...
    f(N)=f(N-1)+f(N-2)
    

    递归解决(自顶向下)

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eDn7QAzG-1569663083177)(E:\F\blog\动态规划.PNG)]

    	public int f(int n){
            if (n <1) {
                return 0;
            }
            if (n == 1){
                return 1;
            }
            if (n == 2){
                return 2;
            }
            return f(n-1) + f(n-2);
        }
    

    从图中我们可以看出,没错,这是一棵二叉树,如图所示,这里同样颜色的表示重复计算的节点,而且多数都不止重复计算了一次。因此可以继续优化。

    备忘录算法–递归优化

    	public int f(int n, Map<Integer,Integer> map){
            if (n <1) {
                return 0;
            }
            if (n == 1){
                return 1;
            }
            if (n == 2){
                return 2;
            }
            if(map.containsKey(n)){
                return map.get(n);
            }else{
                int value = f(n-1,map) + f(n-2,map);
                map.put(n,value);
                return value;
            }
        }
    

    动态规划(自底向上)

    	public int f(int n){
            if (n <1) {
                return 0;
            }
            if (n == 1){
                return 1;
            }
            if (n == 2){
                return 2;
            }
            int a = 1;
            int b = 2;
            int temp = 0;
            for (int i = 3; i < n+1 ; i++) {
                temp = a + b;
                a = b;
                b= temp;
            }
            return temp;
        }
    
总结

动态规划是一种解决复杂问题的方法,它将大问题分成小问题或者说子问题,这些子问题是独立的,且会有重叠,也就是各子问题包含公共的子子问题,动态规划不会重复地求解公共子问题,而是对每个子问题只求解一次,将结果保存起来,从而避免每次遇到各个子问题时重新计算结果。适合采用动态规划方法的最优化问题中的两个要素:最优子结构和重叠子问题。
的方法,它将大问题分成小问题或者说子问题,这些子问题是独立的,且会有重叠,也就是各子问题包含公共的子子问题,动态规划不会重复地求解公共子问题,而是对每个子问题只求解一次,将结果保存起来,从而避免每次遇到各个子问题时重新计算结果。适合采用动态规划方法的最优化问题中的两个要素:最优子结构和重叠子问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值