什么是动态规划?算法之动态规划

概念

不会算法的程序员不是好程序员,动态规划更是经典算法之一,希望这篇小博客能让大家对动态规划有一个简单的入门。
动态规划其基本思想是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。可能未接触过动态规划的人看到就不理解了,下面用例子给大家讲讲我对动态规划的理解
1、入门题——经典爬楼梯问题
2、简单题——经典机器人路径数问题
3、提升题——最短路径问题

(1)经典爬楼梯问题

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到指定的楼梯层数呢?
输入n 输出方法数
输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。

  1. 1 阶 + 1 阶 + 1 阶
  2. 1 阶 + 2 阶
  3. 2 阶 + 1 阶
    要点 :要跳到第i层,只能从第i-1层或者从i-2层跳上去 故得到关系 f[i]=f[i-1]+f[i-2]

下面是代码与解析

class Solution {
  public int climbStairs(int n) { 
 if(n==1) return 1;
 if(n==2) return 2;
 int f[]=new int[n]; //定义数组,储存第i层有f[i]种方法
 f[0]=1;  //跳第一层有1种方法
 f[1]=2;  //跳第一层有2种方法
          //之后利用循环与已知f[0],f[1]求之后的层数 
 for(int i=2;i<f.length;i++) {  //要跳到第i层,只能从第i-1层或者从i-2层跳上去 故得到关系 f[i]=f[i-1]+f[i-2]
                             //注意i应从i=2开始循环  否则数组下标会出错
  f[i]=f[i-1]+f[i-2];  
 }
 return f[n-1];
 }
 }

(2)经典路径数问题

一个机器人从一个m*n网格的最左上角出发,机器人每次只能向下或向右走一步,要走到网格的最右下角共有多少中走法?
要点:既然是m×n的一个网格,那就要用到二维数组dp[m][n],记录走到dp[i][t]位置的网格方法数,得到: dp[i][t]=dp[i-1][t]+dp[i][t-1]
下面是代码与我的分析:

class Solution { 
    public int uniquePaths(int m, int n) {
     int dp[][]=new int[m][n];
     for(int i=0;i<dp.length;i++)
     dp[i][0]=1; //走第一列只有一条路可走
      for(int i=0;i<dp[0].length;i++)
      dp[0][i]=1;//走第一行只有一条路可走     
     for(int i=1;i<dp.length;i++)// 两次循环分别控制二维数组的行和列
     for(int t=1;t<dp[0].len)gth;t++)//主要解析在 要点
       dp[i][t]=dp[i-1][t]+dp[i][t-1];
         return dp[m-1][n-1];
    }
}

(3)、最短路径问题

给定一个矩阵m,从左上角开始每次只能向右或者向下走,最后到达右下角的位置,求到右下角的最短路径数
给定如下:
1 3 5 9
8 0 3 4
5 0 6 1
8 8 4 0
路径1,3,0,0,0,1,0是所有路径中路径和最小的,所以返回5。
要点:二维数组dp[m][n],记录走到dp[i][j]位置的最短路径,得到: dp[i][j]=dp[i-1][j]+dp[i][j-1]
下面是代码与我的分析:

class Solution { 
 public static int shortestRoad(int arr[][])
    {
        int dp[][]=new int [arr.length][arr[0].length]; //储存 走到到dp[i][j]网格的最短路径的和
        dp[0][0]=arr[0][0];
        for(int i=1;i<arr.length;i++)            //思路如上题
        
        {
            dp[i][0]=dp[i-1][0]+arr[i][0];
           
        }
        for(int j=1;j<arr[0].length;j++)
        {
            dp[0][j]=dp[0][j-1]+arr[0][j];
           
        }                                           
        for(int i=1;i<arr.length;i++)
            for(int j=1;j<arr[0].length;j++)
            {
                dp[i][j]=Math.min(dp[i-1][j], dp[i][j-1])+arr[i][j];  // 选取向下或向右这两条中的最短一条 +上当前网格的数
            }
              return dp[arr.length-1][arr[0].length-1];
    }
}

相信大家对动态规划有了一定的理解,接下来大家可以去各大刷题网站刷题,孰能生巧,练多了自然就懂其中的一些套路和做题方法,我举的例子均为经典题,只为让大家有一定的理解,如要学好动态规划,还需多花心思。

猜你喜欢

转载自blog.csdn.net/weixin_44758662/article/details/106660240