动态规划(爬楼梯问题)

来源:互联网 发布:php表单提交数据过滤 编辑:程序博客网 时间:2024/05/16 01:36

动态规划初识(爬楼梯问题)

1.什么是动态规划

   自己的理解就是搜索问题的优化,可以用动归解决的问题都可以用搜索(DFS)来做

2. 动态规划可以解决问题的分类

   1.Maxtrix DP 坐标类型的动归(x,y的二维矩阵,求方案总数等)

   2 Sequence DP 序列的动归(跳跃游戏,打劫房屋,爬楼梯问题)

   3 TWO Sequences DP 双序列的动归问题(两个字符转的比较)

   4 背包问题

     可以看看lintcode上动归的问题,大致分为以上四类

 

3  动态规划的要点

    1.state 状态 f[i] 标识前i个位置/数字/字母

    2.function f[i]=f[j]  j是i之前的位置(j<i),也叫状态转移方程,下一步和上一步的联系是什么

   3. 初始化f[0]

   4. 答案是什么 answer f[i-1]

 

 

例题 爬楼梯问题

假设你正在爬楼梯,需要n步你才能到达顶部。但每次你只能爬一步或者两步,你能有多少种不同的方法爬到楼顶部?

比如n=3,1+1+1=1+2=2+1=3,共有3中不同的方法   返回 3

 

分析 按照上面的要点分析

1  f[i] 标识前爬到i层有多少种方式

2  f[i] 的状态方程,由于只能爬一或者两步  f[i] 是从f[i-2] 或者f[i-1] 来的 f[i] = f[i-1]+f[i-2]

3  初始化状态 f[0] = 1 f[1]=2  f[0]表示前1级台阶的方案数目,f[1] 标识前2级的方案数目

4 answer f[i-1]


分析后 代码就简单了



   动归和搜索的对比

    动态规划完成时间复杂度为O(n)

   这题当然可以用dfs搜索来做

   搜索的方式存在大量的重复计算,如下,例如 dfs(99)=dfs(98)+dfs(97)  dfs(98)=dfs(97)+dfs(96) 其实dfs(97)算了2次,其余的也类似,可以用hash来标记一下算过的值,如果有就直接取值

  不要再去算了,显然dp的方式更好 O(n) 对比O(2的n次方)  将对数级别优化到了O(n)


dp的方式

public int climbStairs(int n) {         int[] f =new int[n];        if (n<=1){            return 1;        }        if(n==2){            return 2;        }        //初始化        f[0]=1;        f[1]=2;        if(n<=2){            return f[n];        }        for(int i=2;i<=n-1;i++){           //状态方程            f[i]=f[i-1]+f[i-2];        }        //结果        return f[n-1];    }


dfs的方式

public int dfs(int n) {      if(n<3)//如果是1或2,分别有1、2种走法直接返回即可       {          return n;      }      else//否则递归!       {         return dfs(n-1)+dfs(n-2);//利用一般表达式来求解(其实就是斐波那契数列)      }     }