题目:
在一个m×n的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次向左或者向下移动一格直到到达棋盘的右下角。给定一个棋盘及其上面的礼物,请计算你最多能拿到多少价值的礼物?
样例:
输入:
[
[2,3,1],
[1,7,1],
[4,6,1]
]
输出:19
解释:沿着路径 2→3→7→6→1 可以得到拿到最大价值礼物。
在线做题: https://www.acwing.com/problem/content/56/
解答:
动态规划,自顶向下进行思考,为避免计算重复子问题,实现时用自下而上的方法
- 第一种实现方法:自顶向下进行递归,同时保存每个小矩阵的value
class Solution(object):
def getMaxValue(self, grid):
"""
:type grid: List[List[int]]
:rtype: int
"""
self.d = {}
m = len(grid)
if m == 0:
return
if len(grid[0]) == 0:
return
else:
n = len(grid[0])
return self.getValue(grid, 0, 0, m, n)
def getValue(self, grid, i, j, m, n):
if i == m - 1:
sum = 0
for jj in range(j, n):
sum += grid[i][jj]
return sum
if j == n - 1:
sum = 0
for ii in range(i, m):
sum += grid[ii][j]
return sum
v = grid[i][j] + max(self.d.get((i + 1, j), self.getValue(grid, i + 1, j, m, n)), self.d.get((i, j + 1), self.getValue(grid, i, j + 1, m, n)))
return v
然而这种方法运行超时。
- 第二种方法:自下向上进行循环实现,剑指Offer提供了另一种实现方式,可以把二维数组优化为只用一维数组
class Solution(object):
def getMaxValue(self, grid):
"""
:type grid: List[List[int]]
:rtype: int
"""
m = len(grid)
if m == 0:
return
if len(grid[0]) == 0:
return
else:
n = len(grid[0])
iplusj = m - 1 + n - 1
result = [[0 for i in range(n)] for j in range(m)]
while(iplusj >= 0):
for i in range(iplusj + 1):
j = iplusj - i
if i >= m or j >= n or i < 0 or j < 0:
continue
else:
if i == m - 1 and j == n - 1:
result[i][j] = grid[i][j]
continue
if i == m - 1:
result[i][j] = grid[i][j] + result[i][j + 1]
continue
if j == n - 1:
result[i][j] = grid[i][j] + result[i + 1][j]
continue
result[i][j] = grid[i][j] + max(result[i][j + 1], result[i + 1][j])
continue
iplusj -= 1
return result[0][0]