• Unique Paths 系列


    Unique Paths Ⅰ

    A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below).

    The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below).

    How many possible unique paths are there?


    Above is a 7 x 3 grid. How many possible unique paths are there?

    Note: m and n will be at most 100.

    Example 1:

    Input: m = 3, n = 2
    Output: 3
    Explanation:
    From the top-left corner, there are a total of 3 ways to reach the bottom-right corner:
    1. Right -> Right -> Down
    2. Right -> Down -> Right
    3. Down -> Right -> Right
    

    Example 2:

    Input: m = 7, n = 3
    Output: 28

     分析:题目比较简单,要求找一个矩阵从左上角到右下角有多少条路,注意只能向右向下走。
    用动态规划求解,三要素如下:
    1、dp[i][j]表示到[i][j]位置的路径数目
    2、初始化:dp[i][0] = 1 dp[0][j] = 1
    3、状态转移方程:到[i][j]位置可以走的路径是[i-1][j]和[i][j-1]之和
    dp[i][j] = dp[i-1][j] + dp[i][j-1]
    代码如下:
     1 class Solution {
     2     public int uniquePaths(int m, int n) {
     3         int M=n;
     4         int N=m;
     5         int[][] dp = new int[M][N];
     6 
     7         dp[0][0] = 1;
     8         for ( int j = 1 ; j < N ; j ++ ) dp[0][j] = 1;
     9         for ( int i = 1 ; i < M ; i ++ ) dp[i][0] = 1;
    10 
    11         for ( int i = 1 ; i < M ; i ++ ){
    12             for ( int j = 1 ; j < N ; j ++ ){
    13                 dp[i][j] = dp[i-1][j]+dp[i][j-1];
    14             }
    15         }
    16         return dp[M-1][N-1];
    17     }
    18 }

    Unique Paths II

    A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below).

    The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below).

    Now consider if some obstacles are added to the grids. How many unique paths would there be?

    An obstacle and empty space is marked as 1 and 0 respectively in the grid.

    Note: m and n will be at most 100.

    Example 1:

    Input:
    [
      [0,0,0],
      [0,1,0],
      [0,0,0]
    ]
    Output: 2
    Explanation:
    There is one obstacle in the middle of the 3x3 grid above.
    There are two ways to reach the bottom-right corner:
    1. Right -> Right -> Down -> Down
    2. Down -> Down -> Right -> Right
    

     分析:这个题比上一个多了障碍条件,也就是当obstacleGrid[i][j]==1时,这个路时不通的。因此这里只需要比上一个题目增加比较节点值是否为1这个判断条件。同时这里要注意如果obstacleGrid[i][j]==1时,对应的dp[i][j]为0。
    代码如下:
     1 class Solution {
     2     public int uniquePathsWithObstacles(int[][] obstacleGrid) {
     3         int M=obstacleGrid.length;
     4         int N=obstacleGrid[0].length;
     5         int[][] dp = new int[M][N];
     6 
     7         dp[0][0] = obstacleGrid[0][0] == 0?1:0;
     8         for ( int j = 1 ; j < N ; j ++ ) {
     9             if( obstacleGrid[0][j-1] == 0 && obstacleGrid[0][j] == 0) dp[0][j] = 1;
    10             else break;
    11         }
    12         for ( int i = 1 ; i < M ; i ++ ) {
    13             if( obstacleGrid[i-1][0] == 0 && obstacleGrid[i][0] == 0) dp[i][0] = 1;
    14             else break;
    15         }
    16 
    17         for ( int i = 1 ; i < M ; i ++ ){
    18             for ( int j = 1 ; j < N ; j ++ ){
    19                 if (obstacleGrid[i][j] == 1) {
    20                     dp[i][j] = 0;
    21                     continue;
    22                 }
    23                 if ( obstacleGrid[i-1][j] == 1 && obstacleGrid[i][j-1] == 0) dp[i][j] = dp[i][j-1];
    24                 else if (obstacleGrid[i-1][j] == 0 && obstacleGrid[i][j-1] == 1) dp[i][j] = dp[i-1][j];
    25                 else if (obstacleGrid[i-1][j] == 0 && obstacleGrid[i][j-1] == 0) dp[i][j] = dp[i-1][j]+dp[i][j-1];
    26                 else dp[i][j] = 0;
    27             }
    28         }
    29         //for ( int i = 0 ; i < M ; i ++ ){
    30         //    for ( int j = 0 ; j < N ; j ++ ){
    31         //        System.out.print(dp[i][j] + "   ");
    32         //    }
    33         //    System.out.println();
    34         //}
    35         return dp[M-1][N-1];
    36     }
    37 }

        运行时间1ms,击败50.34%。还不是很满意,主要是代码比较繁琐,需要进行很多次判断。

    参考了高票答案,果然是巧妙的方法,将二维dp变化成一维dp。

    在状态转移方程中,我们只需要找到dp[i][j]与dp[i-1][j]、dp[i][j-1]的关系,不需要存储整个二维数组。因此这里就可以使用一维数组dp[j] = dp[j] + dp[j - 1]作为状态转移方程,dp[j]与dp[i-1][j]相关,dp[j-1]与dp[i][j-1]相关。

     1 public int uniquePathsWithObstacles(int[][] obstacleGrid) {
     2     int width = obstacleGrid[0].length;
     3     int[] dp = new int[width];
     4     dp[0] = 1;
     5     for (int[] row : obstacleGrid) {
     6         for (int j = 0; j < width; j++) {
     7             if (row[j] == 1)
     8                 dp[j] = 0;
     9             else if (j > 0)
    10                 dp[j] += dp[j - 1];
    11         }
    12     }
    13     return dp[width - 1];
    14 }
     
  • 相关阅读:
    [美团 CodeM 初赛 Round A]最长树链
    [POI2005]Toy Cars
    [CodePlus2017NOV]晨跑
    [JLOI2011]不重复数字
    [NEERC2007][SHOI2008]Cactus Reloaded
    [NOI2015]软件包管理器
    [HAOI2015]树上操作
    CF1097D Makoto and a Blackboard
    Luogu P5339 [TJOI2019]唱、跳、rap和篮球
    HNCPC2019H 有向图
  • 原文地址:https://www.cnblogs.com/boris1221/p/9738596.html
Copyright © 2020-2023  润新知