算法之动态规划类型DP

动态规划类型题
简单类型的DP:fibonacci递推、背包、LIS最长递增序列、LCS最长公共子序列
区间DP:括号匹配、回文串
树形DP:选出权重和最大的节点

走格子----棋盘类的DP
例题:机器人在一个m*n的棋盘上左上角,需要移动到棋盘的右下角,但是只能向下和向右移动,请问有多少条路径可以达到右下角的位置?
动态规划的核心思想是将大问题拆解为小问题
-----**大问题拆分:**棋盘问题可以理解为:走到终点的路径等于走到终点左方位置的路径加上走到终点上方的位置的路径之和
所以可以推导得到状态转移方程
dp(m,n) = dp(m-1,n) + dp(m,n-1)
----**边界情况分析:**当机器人在源点时,此时dp(0,0)=0,
dp(0,y)表示棋盘第一行,只能一直往右走。dp(0,x)=1
dp(x,0)表示第一列,只能一直往下走,所以dp(x,0)=1

具体思路:三个for循环

//初始化一个数组
function sumPath(m,n) {
    //var arr[m][n];  //注意JS中只支持一维数组,二维数组需要利用一维数组来实现。
    //棋盘的第一列
   /* for(let i=0; i<m;i++){
        arr[i][0]=1;
    }
    //棋盘的第一行
   for(let j=0; j<n;i++){
        arr[0][j]=1;
    }*/
    //棋盘的状态转移方程循环
      var arr=[];
    for(let i=0; i<m;i++){
        arr[i]=[];
        for(let j=0;j<n;j++){
            if(i==0||j==0) {
                arr[i][j]=1;
                continue;
            }else {
                  arr[i][j]=arr[i-1][j]+arr[i][j-1];
            }
        }
    }
    return arr[m-1][n-1];
}

青蛙跳台阶问题—三步走分析问题
青蛙一次可以跳一级台阶或者2级台阶,跳上n级台阶有多少种跳法?
----大问题先拆分为小问题
比如;青蛙跳上5级台阶有多少种跳法,考虑青蛙最后一跳可能是跳两级也有可能跳一级,那么问题变成青蛙跳上一个3级台阶和跳上一个四级台阶分别有多少种跳法?
f(5)=f(3)+f(4).那么对于跳上3级台阶和4级台阶可以依次分析,f(3)=f(1)+f(2);f(4)=f(3)+f(2)
-----考虑边界情况
跳一级台阶时,只有一种所以f(1)=1
跳2级台阶有两种跳法,f(2)=2.

-----具体解决问题

function jump(n) {
     if(n<=0)
         return 0;
      if(n==1)
         return 1;
      if(n==2)
         return 2;
    var arr=[];
        arr[0]=0;arr[1]=1;arr[2]=2;
    for(let i=3;i<=n;i++){
        arr[i]=arr[i-1]+arr[i-2];
    }
    return arr[n];
}

最长公共子序列数长度问题
给定两个字符串A和B,返回两个字符串的最长公共子序列的长度。注:最长公共子序列表示是从原有的序列中删掉一些字符后剩余的序列,不连续。与最长子串不同,最长子串是给定序列中某连续部分的一块。如abcdefgj的子串是abcdefg,连续的。
输入已知序列A和B,初始化一个记录数组dp[n][m]
-----大问题分解:如果序列A和序列B的最后一个字符相等即A[n]==B[m],那么最长公共子序列长度等于{A-A[n]与{B-B[m]}的最长公共子序列+1。
若最后的字符不相等即A[n]!==B[m],此时有两种可能,最长公共序列长度等于A序列减去A最后一个字符的序列与B序列的最长公共子序列,或者等于序列A与B序列减去B最后一个字符的序列的最长公共子序列。
-----状态方程如下
dp[i][j]=0,此时i=0或者j=0
dp[i][j]=dp[i-1][j-1]+1,此时i,j>0,A[i]=B[j]
dp[i][j]=max{ dp[i][j-1], dp[i-1][j] },此时A[i]!=B[j]

function LCSLength(arrA,arrB) {
    // var arrLCS=[][];  //JS里不可以直接使用二维数组
    var A = arrA.split("");
    var B= arrB.split("");
     var lengthA=A.length;
     var  lengthB=B.length;
     var  arrLCS=[]; //先定义一个一维数组
     for(let i=0;i<=lengthA;i++) {
         arrLCS[i]=[];   //利用一维数组定义二维数组
         for(let j=0;j<=lengthB;j++) {
             if(i==0||j==0){
                 arrLCS[i][j]=0;
                 continue;
             }
             if(arrA[i-1]==arrB[j-1]) {
                 arrLCS[i][j] = arrLCS[i-1][j-1]+1;
             } else {
                 arrLCS[i][j] =  Math.max{ arrLCS[i-1][j], arrLCS[i][j-1] }
             }
         }
     }
     return arrLCS[lengthA][lengthB];
}

资料:https://www.jianshu.com/p/1a8a8722e598

括号匹配问题
代更
回文串问题
代更
树形DP问题
代更

猜你喜欢

转载自blog.csdn.net/Qian_mos/article/details/89308671
今日推荐