LC每日一题|20240507 - 1463. 摘樱桃 II
给你一个
rows x cols的矩阵grid来表示一块樱桃地。grid中每个格子的数字表示你能获得的樱桃数目。你有两个机器人帮你收集樱桃,机器人 1 从左上角格子
(0,0)出发,机器人 2 从右上角格子(0, cols-1)出发。请你按照如下规则,返回两个机器人能收集的最多樱桃数目:
- 从格子
(i,j)出发,机器人可以移动到格子(i+1, j-1),(i+1, j)或者(i+1, j+1)。- 当一个机器人经过某个格子时,它会把该格子内所有的樱桃都摘走,然后这个位置会变成空格子,即没有樱桃的格子。
- 当两个机器人同时到达同一个格子时,它们中只有一个可以摘到樱桃。
- 两个机器人在任意时刻都不能移动到
grid外面。- 两个机器人最后都要到达
grid最底下一行。
提示:
rows == grid.lengthcols == grid[i].length2 <= rows, cols <= 700 <= grid[i][j] <= 100
题目等级:Hard
解题思路
u1s1,最初刚看到这个血淋淋的Hard的时候,我是非常崩溃的。
五月才过了7天,LC就已经出了4个Hard了,而且其中还有三道dp...这tm让人怎么活呀TvT
冷静下来一看题目,嘿嘿,tm这不就是昨天那道题吗,换汤不换药,甚至更简单了一点...
我们开辟一个三维数组 dp[i][j][k],代表两个机器人分别从起点走到 [i][j] 和 [i][k]格子时所摘取的樱桃总数。
然后我们需要考虑两件事儿
-
对于单个机器人来说,
[x][y]是由谁转移来的?是由
合法的[x - 1][y - 1],[x - 1][y],[x - 1][y + 1]中的最大值+grid[x][y]得到的。 -
如果两个机器人同时走到同一个格子了怎么办?
那就是
j == k的情况了。如果j != k,两个机器人分别拾取自己格子里的;反之如果遇到一起,就只对这个格子拾取1次就好了。
最终返回dp表里的最大值就可以啦~
(这次就先不考虑空间优化的问题咯~
AC代码
class Solution {
fun cherryPickup(grid: Array<IntArray>): Int {
val dp = Array<Array<IntArray>>(grid.size) { Array<IntArray>(grid[0].size) { IntArray(grid[0].size) { Int.MIN_VALUE } } }
dp[0][0][grid[0].size - 1] = grid[0][0] + grid[0].last()
var max = 0
for (i in 1 until grid.size) {
for (j in 0 until grid[0].size) {
for (k in 0 until grid[0].size) {
var pre = dp[i - 1][j][k]
if (j > 0 && k > 0) pre = Math.max(dp[i - 1][j - 1][k - 1], pre)
if (j > 0) pre = Math.max(dp[i - 1][j - 1][k], pre)
if (k > 0) pre = Math.max(dp[i - 1][j][k - 1], pre)
if (j < grid[0].size - 1 && k < grid[0].size - 1) pre = Math.max(dp[i - 1][j + 1][k + 1], pre)
if (j < grid[0].size - 1) pre = Math.max(dp[i - 1][j + 1][k], pre)
if (k < grid[0].size - 1) pre = Math.max(dp[i - 1][j][k + 1], pre)
if (k < grid[0].size - 1 && j > 0) pre = Math.max(dp[i - 1][j - 1][k + 1], pre)
if (j < grid[0].size - 1 && k > 0) pre = Math.max(dp[i - 1][j + 1][k - 1], pre)
dp[i][j][k] = pre + grid[i][j]
if (j != k) dp[i][j][k] += grid[i][k]
max = Math.max(dp[i][j][k], max)
}
}
}
return max
}
}
定义 m = grid.size, n = grid[0].size
时间复杂度:O(mn^2)
空间复杂度:O(mn^2)