总而言之是DP的解法
把问题转换成有2个人从左上向右下走,一共能摘到的樱桃的最大数量
每个人都要走m+n-2
步,走第t
步时的状态可以表示为(t,r1,c1,r2,c2)
当然,这个五元组是冗余的,只需要三维就可以表示这个向量了,因为:
t = r1+c1=r2+c2
在每个时刻,每个人都可以向下或向右,所以总共会产生4种情况:
p1
向下,p2
向下:(t+1,r1+1,c1,r2+1,c2)
p1
向下,p2
向右:(t+1,r1+1,c1,r2,c2+1)
p1
向右,p2
向下:(t+1,r1,c1+1,r2+1,c2)
p1
向右,p2
向右:(t+1,r1,c1+1,r2,c2+1)
状态(t,r1,c1,r2,c2)
的值代表从该状态到终点(m+n-2,m-1,n-1,m-1,n-1)
摘到的樱桃的个数
要注意处理这个状态无法到达终点的情况
这里我们提取出(r1,c1,c2)
作为状态的表示
class Solution(object):
def cherryPickup(self, grid):
"""
:type grid: List[List[int]]
:rtype: int
"""
m = len(grid)
n = len(grid[0])
from collections import defaultdict
mem = defaultdict(lambda:defaultdict(lambda :defaultdict(int)))
mem[m-1][n-1][n-1] = grid[-1][-1]
def isable(i, j, k):
c = i + j - k
return i >= 0 and i < m and j >= 0 and j < n and k >= 0 and k < n and c >= 0 and c < m and grid[i][
j] != -1 and grid[c][k] != -1
def solve(r1, c1, c2):
if r1 not in mem or c1 not in mem[r1] or c2 not in mem[r1][c1]:
res = -1
if isable(r1 + 1, c1, c2):
res = max(res, solve(r1 + 1, c1, c2))
if isable(r1 + 1, c1, c2 + 1):
res = max(res, solve(r1 + 1, c1, c2 + 1))
if isable(r1, c1 + 1, c2 + 1):
res = max(res, solve(r1, c1 + 1, c2 + 1))
if isable(r1, c1 + 1, c2):
res = max(res, solve(r1, c1 + 1, c2))
if res==-1:
mem[r1][c1][c2] = -1
else:
if grid[r1][c1] == 1:
res += 1
if c1 != c2 and grid[r1 + c1 - c2][c2] == 1:
res += 1
mem[r1][c1][c2] = res
return mem[r1][c1][c2]
res = solve(0, 0, 0)
return res if res != -1 else 0
自底身上的DP有可能会遍历许多不可能的情况,需要在循环里就跳过
一个比较好的省空间的方案是取(t,r1,r2)
表示状态,这样状态t
只会与状态t-1
有关
利用背包问题省空间的原理就可以把记录缩小到2维
class Solution(object):
def cherryPickup(self, grid):
"""
:type grid: List[List[int]]
:rtype: int
"""
m = len(grid)
n = len(grid[0])
from collections import defaultdict
mem = defaultdict(lambda:defaultdict(int))
def isable(t, i,c):
j,k = t-i,t-c
return i >= 0 and i < m and j >= 0 and j < n and k >= 0 and k < n and c >= 0 and c < m and grid[i][
j] != -1 and grid[c][k] != -1
for t in xrange(m+n-1):
for r1 in xrange(min(m,t+1),-1,-1):
for r2 in xrange(min(m,t+1),-1,-1):
if isable(t,r1,r2):
res = -1
if isable(t-1,r1,r2):
res = max(res, mem[r1][r2])
if isable(t-1, r1-1,r2):
res = max(res, mem[r1-1][r2])
if isable(t-1,r1,r2-1):
res = max(res, mem[r1][r2-1])
if isable(t-1,r1-1,r2-1):
res = max(res, mem[r1-1][r2-1])
if res == -1 and t!=0:
mem[r1][r2] = -1
else:
if res ==-1:
res = 0
if grid[r1][t-r1] == 1:
res += 1
if r1 != r2 and grid[r2][t - r2] == 1:
res += 1
mem[r1][r2] = res
else:
mem[r1][r2] = -1
return mem[m-1][m-1] if mem[m-1][m-1]!=-1 else 0