https://leetcode.com/problems/cherry-pickup/description/

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.

思路

解答给出的第一种方法时贪心,但是并不是正确答案,正确解法还是万能的dp。

在 t 个steps后,我们到的位置 (r, c),有 r+c=t 。如果有两个人在位置在 t 个steps后在位置 positions (r1, c1) and (r2, c2) 上,那么有 r2 = r1 + c1 - c2。 这意味着变量r1, c1, c2唯一决定了两个都走了r1 + c1 number of steps人的位置。这是我们动态规划思想的基础。

自顶向下的dp:

Let dp[r1][c1][c2] be the most number of cherries obtained by two people starting at (r1, c1) and (r2, c2)and walking towards (N-1, N-1) picking up cherries, where r2 = r1+c1-c2.

If grid[r1][c1] and grid[r2][c2] are not thorns, then the value of dp[r1][c1][c2] is (grid[r1][c1] + grid[r2][c2]), plus the maximum of dp[r1+1][c1][c2]dp[r1][c1+1][c2]dp[r1+1][c1][c2+1]dp[r1][c1+1][c2+1] as appropriate. We should also be careful to not double count in case (r1, c1) == (r2, c2).

Why did we say it was the maximum of dp[r+1][c1][c2] etc.? It corresponds to the 4 possibilities for person 1 and 2 moving down and right:

  • Person 1 down and person 2 down: dp[r1+1][c1][c2];
  • Person 1 right and person 2 down: dp[r1][c1+1][c2];
  • Person 1 down and person 2 right: dp[r1+1][c1][c2+1];
  • Person 1 right and person 2 right: dp[r1][c1+1][c2+1];

要点:1. 将题目中要求的从起始到末尾在返回起始点,等价为二个人同时从起点出发去重点。

      2. 一个三维的dp数组,标记了两个人的位置,以及当前最优解

   3. 子问题之间的关系,要避免重复计算。

代码

class Solution {
int[][][] memo;
int[][] grid;
int N;
public int cherryPickup(int[][] grid) {
this.grid = grid;
N = grid.length;
memo = new int[N][N][N];
for (int[][] layer: memo)
for (int[] row: layer)
Arrays.fill(row, Integer.MIN_VALUE);
return Math.max(0, dp(0, 0, 0));
}
public int dp(int r1, int c1, int c2) {
int r2 = r1 + c1 - c2;
if (N == r1 || N == r2 || N == c1 || N == c2 ||
grid[r1][c1] == -1 || grid[r2][c2] == -1) { //到达边界或者遇到阻碍
return -999999;
} else if (r1 == N-1 && c1 == N-1) {
return grid[r1][c1];
} else if (memo[r1][c1][c2] != Integer.MIN_VALUE) { // 如果这个位置计算过了则不需要再次计算
return memo[r1][c1][c2];
} else {
int ans = grid[r1][c1];
if (c1 != c2) ans += grid[r2][c2];
ans += Math.max(Math.max(dp(r1, c1+1, c2+1), dp(r1+1, c1, c2+1)),
Math.max(dp(r1, c1+1, c2), dp(r1+1, c1, c2)));
memo[r1][c1][c2] = ans;
return ans;
}
}
}

上面是自顶向下的dp。另一中是自低向上的dp:

At time t, let dp[c1][c2] be the most cherries that we can pick up for two people going from (0, 0) to (r1, c1)and (0, 0) to (r2, c2), where r1 = t-c1, r2 = t-c2. Our dynamic program proceeds similarly to Approach 

class Solution {
public int cherryPickup(int[][] grid) {
int N = grid.length;
int[][] dp = new int[N][N];
for (int[] row: dp) Arrays.fill(row, Integer.MIN_VALUE);
dp[0][0] = grid[0][0]; for (int t = 1; t <= 2*N - 2; ++t) {
int[][] dp2 = new int[N][N];
for (int[] row: dp2) Arrays.fill(row, Integer.MIN_VALUE); for (int i = Math.max(0, t-(N-1)); i <= Math.min(N-1, t); ++i) {
for (int j = Math.max(0, t-(N-1)); j <= Math.min(N-1, t); ++j) {
if (grid[i][t-i] == -1 || grid[j][t-j] == -1) continue;
int val = grid[i][t-i];
if (i != j) val += grid[j][t-j];
for (int pi = i-1; pi <= i; ++pi)
for (int pj = j-1; pj <= j; ++pj)
if (pi >= 0 && pj >= 0)
dp2[i][j] = Math.max(dp2[i][j], dp[pi][pj] + val);
}
}
dp = dp2;
}
return Math.max(0, dp[N-1][N-1]);
}
}

LeetCode741. Cherry Pickup的更多相关文章

  1. [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 ...

  2. [LeetCode] 741. Cherry Pickup 捡樱桃

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

  3. [LeetCode] Cherry Pickup 捡樱桃

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

  4. 741. Cherry Pickup

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

  5. LeetCode 741. Cherry Pickup

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

  6. 动态规划-Cherry Pickup

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

  7. [LeetCode] Dungeon Game 地牢游戏

    The demons had captured the princess (P) and imprisoned her in the bottom-right corner of a dungeon. ...

  8. [LeetCode] Minimum Path Sum 最小路径和

    Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which ...

  9. Swift LeetCode 目录 | Catalog

    请点击页面左上角 -> Fork me on Github 或直接访问本项目Github地址:LeetCode Solution by Swift    说明:题目中含有$符号则为付费题目. 如 ...

随机推荐

  1. Mac下安装MacProt,并GNU autotools的安装和使用 autoconf,automake

    1 MacPort的下载:http://www.macports.org/install.php, 需要安装xCode支持macport 2 安装MacPorts 与其他Mac的软件的安装方式相同,挂 ...

  2. Hbase(三) hbase协处理器与二级索引

    一.协处理器—Coprocessor 1. 起源Hbase 作为列族数据库最经常被人诟病的特性包括:无法轻易建立“二级索引”,难以执 行求和.计数.排序等操作.比如,在旧版本的(<0.92)Hb ...

  3. 【learning】快速沃尔什变换FWT

    问题描述 已知\(A(x)\)和\(B(x)\),\(C[i]=\sum\limits_{j\otimes k=i}A[j]*B[k]\),求\(C\) 其中\(\otimes\)是三种位运算的其中一 ...

  4. AES和RSA混合加密技术在网络数据传输中的应用

    原文:http://www.fx361.com/page/2017/0110/519967.shtml          摘要:文章通过分析和比较AES加密算法和RsA加密算法的实现过程和各自的特点, ...

  5. 平衡树【Treap】

    平衡树的板题,用Treap实现. 具体参见注释,写的很详细了,包括了原理,实现以及注意事项 蒟蒻写个注释板子写了两天,太弱了QAQ 感谢niiick指导 Code #include<iostre ...

  6. 782C. Andryusha and Colored Balloons DFS

    Link 题意: 给出一棵树,要求为其染色,并且使任意节点都不与距离2以下的节点颜色相同 思路: 直接DFS.由某节点出发的DFS序列,对于其个儿子的cnt数+1,那么因为DFS遍历的性质可保证兄弟结 ...

  7. python列表排序方法reverse、sort、sorted

    python语言中的列表排序方法有三个:reverse反转/倒序排序.sort正序排序.sorted可以获取排序后的列表.在更高级列表排序中,后两中方法还可以加入条件参数进行排序. reverse() ...

  8. powerdesigner怎么设置同时显示name和code

    实现方法:Tools-Display Preference 从数据库里抽取了数据模型,为了理清思路,需要将name改为中文名称,但是pd自动将name填充为code,可以通过如下配置修改: 选择too ...

  9. 【BZOJ】3992: [SDOI2015]序列统计 NTT+生成函数

    [题意]给定一个[0,m-1]范围内的数字集合S,从中选择n个数字(可重复)构成序列.给定x,求序列所有数字乘积%m后为x的序列方案数%1004535809.1<=n<=10^9,3< ...

  10. JavaScript计时器

    计时器 基本格式: setInterval(function(){代码},1000): /* 说明:1.setInterval 会返回一个计时器ID值 可以这样接收.var setId = setIn ...