LC 741


Solution to LeetCode 741 Cherry Pickup.

LeetCode 741

Cherry Pickup (Hard). [link]

Keys to tackle this problem:

1] Since the problem states that the grid is an N by N 2D array, with 1 <= N <= 50, we can not search (N <= 10, it’s safe to use search).

2] Going from (0,0) to (n-1, n-1) is the same as going from (n-1, n-1) to (0,0). Going forwards and backwards is the same as going backwards twice or two people go backwards. Notice that when they go backwards, if they meet at the same grid with a cherry, only one cherry is counted.

3] There should be two paths (or two positions (x1, y1) and (x2, y2)). We can observe that at each move, these two people are always on the same diagonal line. So we can use three points x1, x2, y1 to represent the two positions, rather than using four points.

4] The state of dynamic programming can be stored in dp[x1, y1, x2], which indicating the max number of cherries picked up so far.

Recursion with memoization. Time complexity O(n^3). Space complexity O(n^3).

class Solution(object):
    def cherryPickup(self, grid):
        """
        :type grid: List[List[int]]
        :rtype: int
        """
        n = len(grid)
        dp = [[[float('-inf')] * n for _ in range(n)] for _ in range(n)]
        
        def Recursion(x1, y1, x2):
            y2 = x1 + y1 - x2
            if x1 < 0 or x2 < 0 or y1 < 0 or y2 < 0: # out of bound
                return -1
            if grid[x1][y1] < 0 or grid[x2][y2] < 0: # -1, blocked
                return -1
            if x1 == 0 and y1 == 0: # reach the end
                return grid[x1][y1]
            if dp[x1][y1][x2] != float('-inf'): # memoization
                return dp[x1][y1][x2]
            
            res = max( 
                max(Recursion(x1 - 1, y1, x2 - 1), Recursion(x1, y1 - 1, x2)),
                max(Recursion(x1, y1 - 1, x2 - 1), Recursion(x1 - 1, y1, x2))
            ) # best move to get most cherries
            
            if res < 0: # cannot find best move, or all moves are blocked
                dp[x1][y1][x2] = -1
            else:
                res += grid[x1][y1] # no duplicate count of cherry
                if x1 != x2: 
                    res += grid[x2][y2]
                dp[x1][y1][x2] = res
            
            return dp[x1][y1][x2]
        
        return max(0, Recursion(n-1, n-1, n-1))
        

  TOC