[LeetCode] 741. Cherry Pickup #741
Open
Comments
谢谢!这个问题太复杂了。小问题:文章中有些地方应该是 q 不是 g |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
In a N x N
grid
representing a field of cherries, each cell is one of three possible integers.Your task is to collect maximum number of cherries possible by following the rules below:
Example 1:
Note:
grid
is anN
byN
2D array, with1 <= N <= 50
.grid[i][j]
is an integer in the set{-1, 0, 1}
.这道题给了我们一个二维数组,每个数字只有三个数字,-1,0,和1,其中-1表示障碍物不能通过,1表示有樱桃并可以通过,0表示没有樱桃并可以通过,并设定左上角为起点,右下角为终点,让我们从起点走到终点,再从终点返回起点,求最多能捡的樱桃的个数,限定起点和终点都没有障碍物。博主开始想的是就用dp来做呗,先从起点走到终点,求最多能捡多个樱桃,然后将捡起樱桃后将grid值变为0,然后再走一遍,把两次得到的樱桃数相加即可,但是类似贪婪算法的dp解法却跪在了下面这个case:
我们可以看出,红色的轨迹是第一次dp解法走过的路径,共拿到了13个樱桃,但是回到起点的话,剩下的两个樱桃无论如何也不可能同时拿到,只能拿到1颗,所以总共只能捡到14颗樱桃,而实际上所有的樱桃都可以捡到,需要换个走法的话,比如下面这种走法:
红色为从起点到终点的走法,共拿到9颗樱桃,回去走蓝色的路径,可拿到6颗樱桃,所以总共15颗都能收入囊中。那这是怎么回事,原因出在了我们的dp递推式的设计上,博主之前设计式,当前位置的樱桃数跟上边和左边的樱桃数有关,取二者的较大值,如果只是从起点到终点走单程的话,这种设计是没有问题的,可以拿到最多的樱桃,但如果是round trip的话,那么就不行了。这里参考的还是fun4LeetCode大神的帖子,范佛利特扣德大神的帖子每次讲解都写的巨详细,总是让博主有种读paper的感觉。博主就挑选部分来讲讲,完整版可以自己去读一读大神的亲笔~
最开始时博主定义的dp[i][j]为单程的,即到达(i, j)位置能捡到的最大樱桃数,即:
但是定义单程就得改变grid的值,再进行一次dp计算时,就会陷入之前例子中的陷阱。所以我们的dp[i][j]还是需要定义为round trip的,即到达(i, j)位置并返回起点时能捡到的最大樱桃数,但是新的问题就来了,樱桃只有一个,只能捡一次,去程捡了,返程就不能再捡了,如何才能避免重复计算呢?我们只有i和j是不够的,其只能定义去程的位置,我们还需要pg,(不是pgone哈哈),来定义返程的位置,那么重现关系Recurrence Relations就变成了 T(i, j, p, g),我们有分别两种方式离开(i, j)和(p, g),我们suppose时从终点往起点遍历,那么就有4种情况:
根据定义,我们有:
因此,我们的重现关系可以写作:
为了避免重复计算,我们希望 grid[i][j] 和 grid[p][g] 不出现在T(i-1, j, p-1, q), T(i-1, j, p, q-1), T(i, j-1, p-1, q) 和 T(i, j-1, p, q-1)中的任意一个上。显而易见的是(i, j)不会出现在(0, 0) ==> (i-1, j) 或 (0, 0) ==> (i, j-1) 的路径上,同理,(p, g) 也不会出现在 (p-1, q) ==> (0, 0) 或 (p, q-1) ==> (0, 0) 的路径上。因此,我们需要保证(i, j) 不会出现在 (p-1, q) ==> (0, 0) 或 (p, q-1) ==> (0, 0) 的路径上,同时 (p, g)不会出现在(0, 0) ==> (i-1, j) 或 (0, 0) ==> (i, j-1) 的路径上,怎么做呢?
我们观察到(0, 0) ==> (i-1, j) 和 (0, 0) ==> (i, j-1) 的所有点都在矩形 [0, 0, i, j] 中(除了右下角点(i, j)点),所以只要 (p, g) 不在矩形 [0, 0, i, j] 中就行了,注意(p, g) 和 (i, j) 是有可能重合了,这种情况特殊处理一下就行了。同理, (i, j) 也不能在矩形 [0, 0, p, g] 中,那么以下三个条件中需要满足一个:
为了满足上述条件,我们希望当 i 或 p 增加的时候,j 或 q 减小,那么我们可以有这个等式:
其中k为从起点开始走的步数,所以我们可以用 T(k, i, p) 来代替 T(i, j, p, g),那么我们的重现关系式就变成了:
当 i == p 时,grid[i][k-i] 和 grid[p][k-p] 就相等了,此时只能加一个。我们注意到 i, j, p, q 的范围是 [0, n), 意味着k只能在范围 [0, 2n - 1) 中, 初始化时 T(0, 0, 0) = grid[0][0]。我们这里的重现关系T虽然是三维的,但是我们可以用二维dp数组来实现,因为第k步的值只依赖于第k-1步的情况,参见代码如下:
类似题目:
Minimum Path Sum
Dungeon Game
参考资料:
https://discuss.leetcode.com/topic/112877/annotated-c-dp-solution
https://discuss.leetcode.com/topic/113762/step-by-step-guidance-of-the-o-n-3-time-and-o-n-2-space-solution
LeetCode All in One 题目讲解汇总(持续更新中...)
The text was updated successfully, but these errors were encountered: