题目描述
这是 LeetCode 上的 741. 摘樱桃 ,难度为 困难。
Tag : 「线性 DP」
一个 的网格( grid
) 代表了一块樱桃地,每个格子由以下三种数字的一种来表示:
你的任务是在遵守下列规则的情况下,尽可能的摘到最多樱桃:
- 从位置出发,最后到达,只能向下或向右走,并且只能穿越有效的格子(即只可以穿过值为或者
- 当到达后,你要继续走,直到返回到
- 当你经过一个格子且这个格子包含一个樱桃时,你将摘到樱桃并且这个格子会变成空的(值变为0);
- 如果在和
示例 1:
说明:
-
grid
是一个的二维数组,N的取值范围是 - 每一个
grid[i][j]
都是集合{-1, 0, 1}
其中的一个数 - 可以保证起点
grid[0][0]
和终点grid[N-1][N-1]
的值都不会是
线性 DP
为了方便,我们令 grid
为 g
,同时调整矩阵横纵坐标从
原问题为先从左上角按照「只能往下 + 只能往右」的规则走到右下角,然后再按照「只能往上 + 只能往左」的规则走回左上角,途径的值为 的格子得一分(只能得分一次,得分后置零),同时不能经过值为
其中第二趟的规则等价于按照第一趟的规则从左上角到右下角再走一遍,再结合每个位置的只能得分一次,可以将原问题等价于:两个点从左上角开始同时走,最终都走到右下角的最大得分。
定义 为当前走了 步(横纵坐标之和),且第一个点当前在第 行,第二点在第 行时的最大得分,最终答案为 ,同时有
由于两个点是同时走(都走了 步),结合「只能往下 + 只能往右」的规则,可直接算得第一个点所在的列为 ,第二点所在的列为 。
不失一般性考虑 该如何转移,两个点均有可能走行或走列,即有 种前驱状态:、、 和 ,在四者中取最大值,同时当前位置 和 的得分需要被累加,假设两者得分别为 和 ,若两个位置不重叠的话,可以同时累加,否则只能累加一次。
一些细节:为了防止从值为 的格子进行转移影响正确性,我们需要先将所有
代码:
- 时间复杂度:状态数量级为,每个状态转移复杂度为。整体复杂度为
- 空间复杂度:
最后
这是我们「刷穿 LeetCode」系列文章的第 No.741
篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。
在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。
为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:github.com/SharingSour… 。
在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。