[英]Dynamic programming to find the maximum cost path of a 2D grid
給定一個二維網格,G 有 q 行和 p 列,其中每個單元格 G[i][j] 包含一個整數。 它需要從左上角 (0,0) 移動到右下角 (q-1,p-1)。 我一次只能左右移動 1 個單位。 當我訪問一個單元格時,單元格 G[i][j] 中的數量被添加到總數中。 我需要最大化總數並獲得路徑。 這是我的第一次嘗試
def findMaxPerson1(q, p, grid, memo={}):
key = f"{q},{p}"
if key in memo:
return memo[key]
if q == 0 and p == 0: # Start point
return grid[0][0]
if q < 0 or p < 0:
return 0
up = findMaxPerson1(q-1, p, grid, memo) # Up
left = findMaxPerson1(q, p-1, grid, memo) # Left
if up >= left:
memo[key] = up + grid[q][p]
return memo[key]
else:
memo[key] = left + grid[q][p]
return memo[key]
我從上面的代碼中得到了 15。 現在我嘗試修改以前的代碼以獲取路徑和最大總數。 這是我的嘗試代碼:
def findMaxPerson1(q, p, grid, memo={}):
key = f"{q},{p}"
if key in memo:
return memo[key]
if q == 0 and p == 0:
return {
'total': grid[q][p],
'path': [(q, p)]
}
if q < 0 or p < 0:
return None
up = findMaxPerson1(q-1, p, grid, memo) # Up
left = findMaxPerson1(q, p-1, grid, memo) # Left
if up is not None and left is not None: # Both are dictionary
if up['total'] >= left['total']:
up['total'] = up['total'] + grid[q][p]
up['path'].append((q, p))
memo[key] = up
return up
else:
left['total'] = left['total'] + grid[q][p]
left['path'].append((q, p))
memo[key] = left
return left
if up is not None:
up['total'] = up['total'] + grid[q][p]
up['path'].append((q, p))
memo[key] = up
return up
else:
left['total'] = left['total'] + grid[q][p]
left['path'].append((q, p))
memo[key] = left
return left
print(findMaxPerson1(2, 1, grid, {}))
將此修改后的代碼與相同的網格一起使用,我得到以下輸出:
{'total': 19, 'path': [(0, 0), (1, 0), (1, 1), (2, 0), (2, 1)]}
這是我使用的網格:
grid = [
[1, 2],
[3, 4],
[5, 6],
]
為什么路徑不對? 有誰知道我做錯了什么? 先感謝您。
第二種方法的問題是您正在重用和更新與memo
多個鍵的值相同的對象。
第一種方法, memo
的值是一個簡單的整數,當你做memo[key] = up + grid[q][p]
,值被復制。 現在up
值和memo[key]
值是完全獨立的。
相反,在第二種方法中,您執行以下操作:
up['total'] = up['total'] + grid[q][p]
up['path'].append((q, p))
memo[key] = up
它up
不復制的情況下修改up
它,現在你在up
和memo[key]
中有相同的對象,它具有相同的更新值。
要解決這個問題簡單的方式將deepcopy的up
和left
修改之前,因為這樣的:
import copy
...
up = copy.deepcopy(up)
left = copy.deepcopy(left)
這解決了問題,現在第二種方法打印:
{'total': 15, 'path': [(0, 0), (1, 0), (2, 0), (2, 1)]}
但這非常低效,因為它每次都復制整個路徑,使您的算法 O(n 4 ) 而不是 O(n²)。
更好的方法是只存儲每個鍵的前一個鍵(而不是整個路徑)。 算法的主要部分完成后,您可以按照此向后引用重建路徑。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.