Unique Paths

Problem definition: Leetcode.

In abstract, given a 2D array find the number of paths to move from the top-left corner to the bottom right corner. The only possible moves from a cell of the grid to the next one are either down or right.

Define the structure of an optimal solution

An optimal solution is represented by the number of paths to move from the top-left corner to any other cell of the grid.

Recursively define the value of an optimal solution

The key observation is that each cell of the grid can be reached only from left or up. So, an optimal solution S for a generic cell with coordinates (i.j) is given by S(i,j) = S(i-1,j) + S(i,j-1).

Compute the value of an optimal solution

The following c++ program implements a solution according to the top-down with memoization approach:

 int uniquePaths(int m, int n) {
        
  if (m <= 0 || n <= 0) return 0;

  vector<vector<int>> dp(n, vector<int>(m,-1));
  dp[0][0] = 1;
  return uniquePathsHelper(m-1, n-1, dp);
}

int uniquePathsHelper(int m, int n, vector<vector<int>>& dp) {

  //Check out of grid coordinates
  if (m < 0 || n < 0) return 0;

  //Check already computed paths
  if (dp[n][m] >= 0) return dp[n][m];
  
  //compute and save unique pths for the current cell
  dp[n][m] =  uniquePathsHelper(m-1, n, dp) + uniquePathsHelper(m, n-1, dp);

  return  dp[n][m];
}

The following python program implements a solution according to the bottom-up approach:

def uniquePaths(m, n):

        if m <= 0 or n <= 0 :
            return 0
        
        #create a grid with m columns and n rows
        dp = [[0]*m for x in range(n)]
        
        #define starting states
        
        #each cell of the first column can be reached only from up
        for i in range(n) :
            dp[i][0] = 1
        
        #each cell of the first row can be reached only from left
        for j in range(m) :
            dp[0][j] = 1      
        
        #compute all states
        for i in range(1,n) :
            for j in range(1,m) :
                dp[i][j] = dp[i-1][j] + dp[i][j-1]
                
        return dp[n-1][m-1]

An extension of this problem considers that some obstacles are added to the grid, so that it’s not possible to move in a cell with an obstacle. The recurrence formula defining the value of an optimal solution is very similar to the previous one, except that S(i,j) = 0 if the cell (i,j) contains an obstacle. The following python programs solves this problem, assuming that the value of a cell is 1 if there is an onstacle and 0 otherwise:

def uniquePathsWithObstacles (obstacleGrid):

  rows = len(obstacleGrid)    # 3 rows in your example
  cols = len(obstacleGrid[0])

  if rows <= 0 or cols <= 0 :
    return 0

  dp = [[0]*cols for i in range(rows)] 
  
  #define starting states
  for x in range(rows) :
    if obstacleGrid[x][0] == 1 :
      break
    dp[x][0] = 1

  for y in range(cols) :
    if obstacleGrid[0][y] == 1 :
      break
    dp[0][y] = 1

  for x in range(1,rows) :
      for y in range(1,cols) :
        dp[x][y] = dp[x-1][y] + dp[x][y-1] if obstacleGrid[x][y] == 0 else 0

  return dp[rows-1][cols-1]

Comments