动态规划介绍及算法题

一个例子来了解动态规划

用“斐波那契数”这个题来了解什么是动态规划
在这里插入图片描述
代码实现:

public class t {
    public static void main(String[] args) {


        int j = f(9);
        System.out.println(j);

    }

    public static int f(int n){
        if(n ==1){
            return 1;
        }
        if(n==2){

            return 1;
        }
        int c = f(n-1)+f(n-2);
        return c;

    }

}

这里是用递归来实现的;

接下来我们来分析一下每次计算一个数的是由有没有重复计算的过程
在这里插入图片描述
优化版本

import java.util.HashMap;

public class t {
    public static void main(String[] args) {
        HashMap<Integer,Integer> aa = new HashMap<>();
        int j = f(7,aa);
        System.out.println(j);
    }

    public static int f(int n,HashMap<Integer,Integer> a1){

        if(a1.get(n)!=null){
            return a1.get(n);

        }

        if(n ==1){
            a1.put(1,1);
            return 1;
        }
        if(n==2){
             a1.put(2,1);
            return 1;
        }
        int c = f(n-1,a1)+f(n-2,a1);
        a1.put(n,c);
        return c;

    }

}

进阶优化
我们可以用数组来搞定这个问题
代码:

public static int dd(int a){
        if(a==1||a==2){
            return 1;
        }
        int[] arr = new int[a+1];
        arr[1] = 1;
        arr[2] = 1;
        for (int i = 3;i<arr.length;i++){
            arr[i] = arr[i-1]+arr[i-2];


        }
        return arr[a];




}

这就是最终的动态规划

相关算法题

1.机器人走路

在这里插入图片描述
我们就根据题意来完成递归代码

public class t {
    public static void main(String[] args) {
       int a1 = way(5,13,10,100);

        System.out.println(a1);



    }

    public static int way(int star,int get,int ret,int N){
        if(ret==0){

            return star==get?1:0;

        }
        if(star==1){
           return way(star+1,get,ret-1,N);
        }
        if(star==N){

          return way(star-1,get,ret-1,N);
        }

        int a3 =  way(star+1,get,ret-1,N);
         int a4 =  way(star-1,get,ret-1,N);
       return a3+a4;




    }

}

这个就是递归版本的解法
同样的我们来进行优化
这次我们直接把它改成用数组来计算,可以看到每次传入递归函数的变量有两个,因此我们可以创建一个二维数组来记录

    public static int dp(int star,int get,int ret,int N){
          int[][] arr = new int[N+1][ret+1];
          arr[get][0] = 1;
          for(int i = 1;i<ret+1;i++){

              for(int j = 1;j<N+1;j++){

                  if(j==1){

                     arr[j][i] =arr[j+1][i-1];
                      continue;
                  }
                  if(j==N){
                      arr[j][i] =arr[j-1][i-1];
                      continue;

                  }
                  arr[j][i] = arr[j+1][i-1]+arr[j-1][i-1];



              }

          }
          return arr[star][ret];




    }

这样我们就完成了

2.先手后手抽牌

在这里插入图片描述
递归代码:

public class t {

    public static void main(String[] args) {
        int[] arr = {20,100,3,2};
        int a = xian(arr,0,3);
        System.out.println(a);


    }
    public static int xian(int[] arr,int l,int r){
        if(l==r){
            return arr[l];
        }
        int a1 = arr[l]+hou(arr,l+1,r);
        int a2 = arr[r] +hou(arr,l,r-1);
        return Math.max(a1,a2);


    }

    public static int hou(int[]arr,int l,int r){
        if(l==r){
            return arr[l];
        }
        int a1 = xian(arr,l+1,r);
        int a2 = xian(arr,l,r-1);
        return Math.min(a1,a2);



    }






}

经过分析后可以知道,这个递归函数有重复计算过程因此我们可以进行优化
优化后代码:

public class t {

    public static void main(String[] args) {
        int[] arr = {20,100,3,2};

        System.out.println(qq(arr));


    }
    public static int qq(int[] arr){
        int[][] xian = new int[arr.length][arr.length];
        int[][] hou = new int[arr.length][arr.length];
        for (int i = 0;i<arr.length;i++){
            for (int k =0;k<arr.length;k++){
                xian[i][k] = -1;
                hou[i][k] = -1;

            }

        }
        return xian(arr,0,arr.length-1,xian,hou);


    }






    public static int xian(int[] arr,int l,int r,int[][] xain,int[][]hou){
        if(xain[l][r]!=-1){
            return xain[l][r];
        }

        if(l==r){
            xain[l][l] = arr[l];
            return arr[l];
        }
        int a1 = arr[l]+hou(arr,l+1,r,xain,hou);
        int a2 = arr[r] +hou(arr,l,r-1,xain,hou);
        int c = Math.max(a1,a2);
        xain[l][r] = c;
        return c;


    }

    public static int hou(int[]arr,int l,int r,int[][] xain,int[][] hou ){
        if(hou[l][r]!=-1){
            return hou[l][r];
        }
        if(l==r){
          return 0;
        }
        int a1 = xian(arr,l+1,r,xain,hou);
        int a2 = xian(arr,l,r-1,xain,hou);
        int c = Math.min(a1,a2);
        hou[l][r] = c;
        return c;



    }

}

同样是建立表去记录已将算过的值
接下来直接用两个二维数组来代替这个递归

    public static int gg(int[] arr){
        int[][] xian = new int[arr.length][arr.length];
        int[][] hou = new int[arr.length][arr.length];
        for (int i = 0;i<arr.length;i++){
            xian[i][i] = arr[i];

        }
        int N=arr.length;
        for (int startCol = 1; startCol < N; startCol++) {
            int L = 0;
            int R = startCol;
            while (R < N) {
                int i = L;
                int k = R;

                int a1 = arr[i] + hou[i + 1][k];
                int a2 = arr[k] + hou[i][k - 1];
                xian[i][k] = Math.max(a1, a2);
                int a11 = xian[i][k - 1];
                int a22 = xian[i + 1][k];
                hou[i][k] = Math.min(a11, a22);

                L++;
                R++;
            }
        }

        return Math.max(xian[0][arr.length-1],hou[0][arr.length-1]);





    }

3.背包问题

题意描述:
给定两个数组一个数组记录物品的价值,一个数组记录物品的重量,数组的下标代表物品的编号,再给定一个背包能装下的最大重量,求出可以取得的最大价值数

这道题我们可以直接进行暴力递归来算,就是把每一种情况的算出来然后找出最大值
递归代码展示:

public class t {

    public static void main(String[] args) {
        int[] a1 = {12,3,100,12,46,78};
        int[] a2 = {2,4,5,2,63,4};
        System.out.println(jia(a1, a2, 10, 0));
       

    }
    
    public static int jia(int[] v,int[] b,int bag ,int i){
        if(bag==0||i==v.length){
            return 0;
        }
        int a1 = 0;
        if(bag-b[i]>=0) {
             a1 = v[i] + jia(v, b, bag - b[i], i + 1);
        }
        int a2 = jia(v,b,bag,i+1);
        return Math.max(a1,a2);


    }






}

这个同样也可以进行优化:

 public static int biao(int[] v,int[] b,int bag ){
        int[][] aa = new int[v.length][bag+1];
        for (int i =v.length-1;i>=0;i--){

            for(int k = 1;k<=bag;k++){

                int a1 = 0;
                int a2 = 0;
                if(k-b[i]>=0) {
                    a1 = v[i] + jia(v, b, bag - b[i], i + 1);
                }
                a2 = jia(v,b,bag,i+1);
                aa[i][k] =  Math.max(a1,a2);
            }



        }


        return aa[0][bag];
    }

3.字符串转化

在这里插入图片描述
递归代码展示:

public class t {
    public static void main(String[] args) {
        String aa = "305";
        char[] a  =aa.toCharArray();
        System.out.println(zu(a, 0));


    }

public static int zu(char[] arr,int i){
        if(i==arr.length){
            return 1;
        }
        if(arr[i]=='0'){
            return 0;

        }

        int a1 =zu(arr,i+1);
        if(i+1!=arr.length&&(arr[i]-'0')*10+(arr[i+1]-'0')<27){

            a1 +=zu(arr,i+2);
        }
        return a1;


}



}

优化代码:

    public static int biao(char[] arr){
        int[] aa = new int[arr.length+1];
        for(int i = arr.length;i>=0;i--){
            if(i==arr.length){
               aa[i]=1;
               continue;
            }
            if(arr[i]=='0'){
                aa[i] =  0;
                continue;

            }

            int a1 =aa[i+1];
            if(i+1!=arr.length&&(arr[i]-'0')*10+(arr[i+1]-'0')<27){

                a1 +=aa[i+2];
            }
            aa[i] = a1;



        }
        return aa[0];



    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值