- Leetcode 3363. Find the Maximum Number of Fruits Collected
- 1. 解题思路
- 2. 代码实现
- 题目链接:3363. Find the Maximum Number of Fruits Collected
1. 解题思路
这一题是一道陷阱题……
乍一眼看过去,由于三人的路线完全可能重叠,因此需要考虑路线当中果子是否有被取走的情况,就会变得异常复杂,完全想不到解答的思路。
但是后续仔细一看题目,要求三人都必须在 n − 1 n-1 n−1步之后走到点 ( n − 1 , n − 1 ) (n-1, n-1) (n−1,n−1),因此这道题就被大大简化了,因为:
- 对于第一个孩子而言,虽然可走的路线非常多,但是要求 n − 1 n-1 n−1步之后走到点 ( n − 1 , n − 1 ) (n-1, n-1) (n−1,n−1),他能走的路线事实上也就是沿着对角线的最短路线了;
- 对于第二个孩子,由于终点必须走到点 ( n − 1 , n − 1 ) (n-1, n-1) (n−1,n−1),因此事实上他最远能走到的位置也就是对角线的位置,而由于对角线上的果子必然都被第一个孩子拿走了,因此他事实上只会在对角线的上方行走,只有在最后一步会走到 ( n − 1 , n − 1 ) (n-1, n-1) (n−1,n−1)。
- 同样对于第三个孩子,出于同样的限制条件,他事实上也只会在对角线下方行走,且最后一步会走到 ( n − 1 , n − 1 ) (n-1, n-1) (n−1,n−1)。
因此,事实上三人的路线是完全不会重合的,或者说最优方案中三人的路线必然不重合,因此我们只需要分别独立考察第二和第三个孩子的最优路线即可,而这就是两个简单的动态规划的问题了。
2. 代码实现
给出python代码实现如下:
class Solution:
def maxCollectedFruits(self, fruits: List[List[int]]) -> int:
n = len(fruits)
s1 = sum(fruits[i][i] for i in range(n))
@lru_cache(None)
def dp1(i, j):
if i == n-2 and j == n-1:
return fruits[i][j]
ans = -math.inf
for k in range(j-1, j+2):
if k < n and k > i:
ans = max(ans, fruits[i][j] + dp1(i+1, k))
return ans
@lru_cache(None)
def dp2(i, j):
if i == n-1 and j == n-2:
return fruits[i][j]
ans = -math.inf
for k in range(i-1, i+2):
if k < n and k > j:
ans = max(ans, fruits[i][j] + dp2(k, j+1))
return ans
return s1 + dp1(0, n-1) + dp2(n-1, 0)
提交代码评测得到:耗时1946ms,占用内存297.3MB。