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.

64. Minimum Path Sum 类似,但这个题还要返回到起点,而且捡过的位置由1变为0,如果分别计算去时和回来时的路径,就要把捡过的变为0,会很麻烦。

解法:DP, 同时计算去和回的dp值。

参考:Grandyang

https://leetcode.com/problems/cherry-pickup/discuss/109903/Step-by-step-guidance-of-the-O(N3)-time-and-O(N2)-space-solution

Java:

public int cherryPickup(int[][] grid) {
int N = grid.length, M = (N << 1) - 1;
int[][] dp = new int[N][N];
dp[0][0] = grid[0][0]; for (int n = 1; n < M; n++) {
for (int i = N - 1; i >= 0; i--) {
for (int p = N - 1; p >= 0; p--) {
int j = n - i, q = n - p; if (j < 0 || j >= N || q < 0 || q >= N || grid[i][j] < 0 || grid[p][q] < 0) {
dp[i][p] = -1;
continue;
} if (i > 0) dp[i][p] = Math.max(dp[i][p], dp[i - 1][p]);
if (p > 0) dp[i][p] = Math.max(dp[i][p], dp[i][p - 1]);
if (i > 0 && p > 0) dp[i][p] = Math.max(dp[i][p], dp[i - 1][p - 1]); if (dp[i][p] >= 0) dp[i][p] += grid[i][j] + (i != p ? grid[p][q] : 0)
}
}
} return Math.max(dp[N - 1][N - 1], 0);
}

Python:

class Solution(object):
def cherryPickup(self, grid):
"""
:type grid: List[List[int]]
:rtype: int
"""
# dp holds the max # of cherries two k-length paths can pickup.
# The two k-length paths arrive at (i, k - i) and (j, k - j),
# respectively.
n = len(grid)
dp = [[-1 for _ in xrange(n)] for _ in xrange(n)]
dp[0][0] = grid[0][0]
max_len = 2 * (n-1)
directions = [(0, 0), (-1, 0), (0, -1), (-1, -1)]
for k in xrange(1, max_len+1):
for i in reversed(xrange(max(0, k-n+1), min(k+1, n))): # 0 <= i < n, 0 <= k-i < n
for j in reversed(xrange(i, min(k+1, n))): # i <= j < n, 0 <= k-j < n
if grid[i][k-i] == -1 or grid[j][k-j] == -1:
dp[i][j] = -1
continue
cnt = grid[i][k-i]
if i != j:
cnt += grid[j][k-j]
max_cnt = -1
for direction in directions:
ii, jj = i+direction[0], j+direction[1]
if ii >= 0 and jj >= 0 and dp[ii][jj] >= 0:
max_cnt = max(max_cnt, dp[ii][jj]+cnt)
dp[i][j] = max_cnt
return max(dp[n-1][n-1], 0)  

Python:

class Solution(object):
def cherryPickup(self, grid):
"""
:type grid: List[List[int]]
:rtype: int
"""
if grid[-1][-1] == -1: return 0 # set up cache
self.grid = grid
self.memo = {}
self.N = len(grid) return max(self.dp(0, 0, 0, 0), 0) def dp(self, i1, j1, i2, j2):
# already stored: return
if (i1, j1, i2, j2) in self.memo: return self.memo[(i1, j1, i2, j2)] # end states: 1. out of grid 2. at the right bottom corner 3. hit a thorn
N = self.N
if i1 == N or j1 == N or i2 == N or j2 == N: return -1
if i1 == N-1 and j1 == N-1 and i2 == N-1 and j2 == N-1: return self.grid[-1][-1]
if self.grid[i1][j1] == -1 or self.grid[i2][j2] == -1: return -1 # now can take a step in two directions at each end, which amounts to 4 combinations in total
dd = self.dp(i1+1, j1, i2+1, j2)
dr = self.dp(i1+1, j1, i2, j2+1)
rd = self.dp(i1, j1+1, i2+1, j2)
rr = self.dp(i1, j1+1, i2, j2+1)
maxComb = max([dd, dr, rd, rr]) # find if there is a way to reach the end
if maxComb == -1:
out = -1
else:
# same cell, can only count this cell once
if i1 == i2 and j1 == j2:
out = maxComb + self.grid[i1][j1]
# different cell, can collect both
else:
out = maxComb + self.grid[i1][j1] + self.grid[i2][j2] # cache result
self.memo[(i1, j1, i2, j2)] = out
return out    

C++:

class Solution {
public:
int cherryPickup(vector<vector<int>>& grid) {
int n = grid.size(), mx = 2 * n - 1;
vector<vector<int>> dp(n, vector<int>(n, -1));
dp[0][0] = grid[0][0];
for (int k = 1; k < mx; ++k) {
for (int i = n - 1; i >= 0; --i) {
for (int p = n - 1; p >= 0; --p) {
int j = k - i, q = k - p;
if (j < 0 || j >= n || q < 0 || q >= n || grid[i][j] < 0 || grid[p][q] < 0) {
dp[i][p] = -1;
continue;
}
if (i > 0) dp[i][p] = max(dp[i][p], dp[i - 1][p]);
if (p > 0) dp[i][p] = max(dp[i][p], dp[i][p - 1]);
if (i > 0 && p > 0) dp[i][p] = max(dp[i][p], dp[i - 1][p - 1]);
if (dp[i][p] >= 0) dp[i][p] += grid[i][j] + (i != p ? grid[p][q] : 0);
}
}
}
return max(dp[n - 1][n - 1], 0);
}
};

  

All LeetCode Questions List 题目汇总

[LeetCode] 741. Cherry Pickup 捡樱桃的更多相关文章

  1. [LeetCode] Cherry Pickup 捡樱桃

    In a N x N grid representing a field of cherries, each cell is one of three possible integers. 0 mea ...

  2. LeetCode 741. Cherry Pickup

    原题链接在这里:https://leetcode.com/problems/cherry-pickup/ 题目: In a N x N grid representing a field of che ...

  3. 741. Cherry Pickup

    In a N x N grid representing a field of cherries, each cell is one of three possible integers. 0 mea ...

  4. [Swift]LeetCode741. 摘樱桃 | Cherry Pickup

    In a N x N grid representing a field of cherries, each cell is one of three possible integers. 0 mea ...

  5. Java实现 LeetCode 741 摘樱桃(DFS || 递推 || 传纸条)

    741. 摘樱桃 一个N x N的网格(grid) 代表了一块樱桃地,每个格子由以下三种数字的一种来表示: 0 表示这个格子是空的,所以你可以穿过它. 1 表示这个格子里装着一个樱桃,你可以摘到樱桃然 ...

  6. LeetCode741. Cherry Pickup

    https://leetcode.com/problems/cherry-pickup/description/ In a N x N grid representing a field of che ...

  7. 动态规划-Cherry Pickup

    2020-02-03 17:46:04 问题描述: 问题求解: 非常好的题目,和two thumb其实非常类似,但是还是有个一点区别,就是本题要求最后要到达(n - 1, n - 1),只有到达了(n ...

  8. leetcode动态规划题目总结

    Hello everyone, I am a Chinese noob programmer. I have practiced questions on leetcode.com for 2 yea ...

  9. LeetCode All in One题解汇总(持续更新中...)

    突然很想刷刷题,LeetCode是一个不错的选择,忽略了输入输出,更好的突出了算法,省去了不少时间. dalao们发现了任何错误,或是代码无法通过,或是有更好的解法,或是有任何疑问和建议的话,可以在对 ...

随机推荐

  1. 下载恶意pcap包的网站

    说几个我经常用的,免费的:1.  Malware  Traffic  Analysis:  http://www.malware-traffic-analysis.net/2018/index.htm ...

  2. poj1679The Unique MST(次小生成树模板)

    次小生成树模板,别忘了判定不存在最小生成树的情况 #include <iostream> #include <cstdio> #include <cstring> ...

  3. Jenkins持续集成邮件发送

    jenkins下载:https://jenkins.io/downloadgeneric java package(war) 1.tomcat部署: 0.jdk环境 1.修改conf目录下的serve ...

  4. LGOJP1850 换教室

    题目地址 https://www.luogu.org/problem/P1850 题解 这题的转移其实挺好想的但是方程特别长...真的特别长... 首先设\(f[i,j,0/1]\)表示当前在第\(i ...

  5. SparkSQL读写外部数据源--数据分区

    import com.twq.dataset.Utils._ import org.apache.spark.sql.{SaveMode, SparkSession} object FileParti ...

  6. 《团队作业第三、第四周》五阿哥团队作业--Scrum 冲刺阶段--Day1--领航

    <团队作业第三.第四周>五阿哥团队作业--Scrum 冲刺阶段--Day1--领航 各个成员在 Alpha 阶段认领的任务 在团队合作时任务也会动态分配,最终以实际为主,上述具有参考价值. ...

  7. 公告 & 备注

    公告 这个\(blog\)从\(2019.12.21\)正式开始使用. 之前的博客请出门右转链接: \[\Large\texttt{my blog}\] \(:)\) 备注 近期要学的算法qwq \( ...

  8. Linear Discriminant Analysis Algorithm

    线性判别分析算法. 逻辑回归是一种分类算法,传统上仅限于两类分类问题. 如果有两个以上的类,那么线性判别分析算法是首选的线性分类技术.LDA的表示非常直接.它包括数据的统计属性,为每个类计算.对于单个 ...

  9. LeetCode 1060. Missing Element in Sorted Array

    原题链接在这里:https://leetcode.com/problems/missing-element-in-sorted-array/ 题目: Given a sorted array A of ...

  10. 一天一经典Efficient Estimation of Word Representations in Vector Space

    摘要 本文提出了两种从大规模数据集中计算连续向量表示(Continuous Vector Representation)的计算模型架构.这些表示的有效性是通过词相似度任务(Word Similarit ...