741. Cherry Pickup

📋 Đề Bài

You are given an n x n grid representing a field of cherries, each cell is one of three possible integers.

  • 0 means the cell is empty, so you can pass through,
  • 1 means the cell contains a cherry that you can pick up and pass through, or
  • -1 means the cell contains a thorn that blocks your way.

Return the maximum number of cherries you can collect by following the rules below:

  • Starting at the position (0, 0) and reaching (n - 1, n - 1) by moving right or down through valid path cells (cells with value 0 or 1).
  • After reaching (n - 1, n - 1), returning to (0, 0) by moving left or up through valid path cells.
  • When passing through a path cell containing a cherry, you pick it up, and the cell becomes an empty cell 0.
  • If there is no valid path between (0, 0) and (n - 1, n - 1), then no cherries can be collected.

 

Example 1:

Input: grid = [[0,1,-1],[1,0,-1],[1,1,1]]
Output: 5
Explanation: The player started at (0, 0) and went down, down, right right to reach (2, 2).
4 cherries were picked up during this single trip, and the matrix becomes [[0,1,-1],[0,0,-1],[0,0,0]].
Then, the player went left, up, up, left to return home, picking up one more cherry.
The total number of cherries picked up is 5, and this is the maximum possible.

Example 2:

Input: grid = [[1,1,-1],[1,-1,1],[-1,1,1]]
Output: 0

 

Constraints:

  • n == grid.length
  • n == grid[i].length
  • 1 <= n <= 50
  • grid[i][j] is -1, 0, or 1.
  • grid[0][0] != -1
  • grid[n - 1][n - 1] != -1

🧠 Thuật Toán & Kỹ Thuật

Dynamic Programming (Quy hoạch động)DFS (Tìm kiếm theo chiều sâu)Bit Manipulation (Thao tác bit)Matrix (Ma trận)
⏱️ Thời gian O(n×m)
💾 Không gian O(n×m)

💻 Lời Giải

C++ 0741-cherry-pickup.cpp
const int maxn = 51;
int dp[maxn][maxn][maxn][maxn];

class Solution {
private:
    int n;
    vector<vector<int>> grid;
    
public:
    int dfs(int r1, int c1, int r2, int c2) {
        if (r1 == n or c1 == n or r2 == n or c2 == n) {
            return INT_MIN;
        }
        
        if (grid[r1][c1] == -1 or grid[r2][c2] == -1) {
            return INT_MIN;
        }
        
        if (dp[r1][c1][r2][c2] != -1) {
            return dp[r1][c1][r2][c2];
        }
        
        if (r1 == n - 1 and c1 == n - 1 and r2 == n - 1 and c2 == n - 1) {
            return grid[r1][c1];
        }
        
        int rr = dfs(r1, c1 + 1, r2, c2 + 1);
        int dd = dfs(r1 + 1, c1, r2 + 1, c2);
        int dr = dfs(r1 + 1, c1, r2, c2 + 1);
        int rd = dfs(r1, c1 + 1, r2 + 1, c2);
        
        int maxComb = max({rr, dd, dr, rd});
        
        if (r1 == r2 and c1 == c2) {
            maxComb += grid[r1][c1];
        }
        else {
            maxComb += grid[r1][c1] + grid[r2][c2];
        }
        
        return dp[r1][c1][r2][c2] = maxComb;
    }
    
    int cherryPickup(vector<vector<int>>& grid) {
        this->n = grid.size();
        memset(dp, -1, sizeof(dp));
        this->grid = grid;
        return max(dfs(0, 0, 0, 0), 0);
    }
};