LeetCode 741. Cherry Pickup(动态规划)

本文解析了LeetCode上的经典问题“樱桃收集”,这是一个关于动态规划的难题。任务是在一个N x N网格中,通过合理路径最大化收集樱桃的数量,同时避免障碍。文章详细介绍了问题背景、解决方案思路及实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目来源:https://leetcode.com/problems/cherry-pickup/

问题描述

741. Cherry Pickup

Hard

In a 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;
  • -1 means the cell contains a thorn that blocks your way.

 

Your task is to collect maximum number of cherries possible 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.

 

Note:

  • grid is an N by N 2D array, with 1 <= N <= 50.
  • Each grid[i][j] is an integer in the set {-1, 0, 1}.
  • It is guaranteed that grid[0][0] and grid[N-1][N-1] are not -1.

------------------------------------------------------------

题意

一个二维数组grid,单元格或不能通行(-1),或有樱桃(1),或为空(0),从左上走到右下再走回左上,求一路可以捡到的樱桃数量的最大值,如果从左上到右下走不通,则返回0

------------------------------------------------------------

思路

注意到第一遍从左上走到右下的时候矩阵grid已经发生了变化,因此不能用两次动态规划解决此问题。

正确的做法是让两个人同时从左上走到右下(或从右下走到左上),乍看起来是一个四维的动态规划问题, dp[x1][y1][x2][y2]分别表示从第一个人从左上走到(x1, y1)且第二个人从左上走到(x2, y2)的最大樱桃数,但是由于两个人是同步走的,因此x1 + y1 = x2 + y2,实际只有3个自由变量,是三维动态规划dp[x1][y1][x2]. 状态转移的时候注意判断状态不可达的情况。

------------------------------------------------------------

代码

class Solution {
    public int cherryPickup(int[][] grid) {
        int n = grid.length;
        if (n == 0) {
            return 0;
        }
        int[][][] dp = new int[n][n][n];
        for (int[][] arr2: dp) {
            for (int[] arr1: arr2) {
                Arrays.fill(arr1, Integer.MIN_VALUE);
            }
        }
        if (grid[0][0] == -1 || grid[n-1][n-1] == -1) {
            return 0;
        }
        dp[0][0][0] = grid[0][0];
        for (int x1=0; x1<n; ++x1) {
            for (int y1=0; y1<n; ++y1) {
                for (int x2=0; x2<n; ++x2) {
                    if (x1 == 0 && y1 == 0 && x2 == 0) {
                        continue;
                    }
                    int y2 = x1 + y1 - x2;
                    if (y2 < 0 || y2 >= n) {
                        continue;
                    }
                    if (grid[x1][y1] == -1 || grid[x2][y2] == -1) {
                        continue;
                    }
                    if (x1 == x2) {
                        dp[x1][y1][x2] = grid[x1][y1];
                    } else {
                        dp[x1][y1][x2] = grid[x1][y1] + grid[x2][y2];
                    }
                    int tmp = -1;   // unrechable flag
                    if (x1 > 0 && x2 > 0 && dp[x1-1][y1][x2-1] > tmp) {
                        tmp = dp[x1-1][y1][x2-1];
                    }
                    if (x1 > 0 && y2 > 0 && dp[x1-1][y1][x2] > tmp) {
                        tmp = dp[x1-1][y1][x2];
                    }
                    if (y1 > 0 && x2 > 0 && dp[x1][y1-1][x2-1] > tmp) {
                        tmp = dp[x1][y1-1][x2-1];
                    }
                    if (y1 > 0 && y2 > 0 && dp[x1][y1-1][x2] > tmp) {
                        tmp = dp[x1][y1-1][x2];
                    }
                    if (tmp != -1) {                // reachable
                        dp[x1][y1][x2] += tmp;
                    } else {                        // unrechable
                        dp[x1][y1][x2] = Integer.MIN_VALUE;
                    }
                }
            }
        }
        return dp[n-1][n-1][n-1] < 0? 0: dp[n-1][n-1][n-1];
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值