【问题标题】:Dynamic programming to find the maximum cost path of a 2D grid寻找二维网格的最大成本路径的动态规划
【发布时间】:2021-12-23 08:16:51
【问题描述】:

给定一个二维网格,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],
]

为什么路径不正确? 有谁知道我做错了什么?提前谢谢你。

【问题讨论】:

  • 我们无法看到路径不正确。你能提供输入吗?
  • 问题描述不清楚。 “它需要从 (0,0) 移动到 (q-1,p-1),并且访问的单元格的总数最大。” — 为什么访问所有单元格或无限地绕圈走不是回答?是否还有您未提及的其他限制?
  • 您的第一次尝试也输出了不正确的19。另外,您只允许向两个方向移动还是四个方向都移动?代码暗示 2,但您在问题陈述中没有提到这一点。
  • 现在您的代码是从右下角到左上角,但问题陈述是从左上角到右下角。
  • 我已经编辑了帖子并详细说明了这个问题。

标签: python algorithm dynamic-programming


【解决方案1】:

第二种方法的问题在于,您正在重用和更新与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 而不复制它,现在您在upmemo[key] 中拥有相同的对象,它具有相同的更新值。


解决问题的天真的方法是在修改之前deepcopyupleft,例如:

import copy
...
up = copy.deepcopy(up)
left = copy.deepcopy(left)

这解决了这个问题,现在第二种方法打印出来了:

{'total': 15, 'path': [(0, 0), (1, 0), (2, 0), (2, 1)]}

但这非常低效,因为它每次都复制整个路径,使您的算法 O(n4) 而不是 O(n²)。

更好的方法是只存储每个键的前一个键(而不是整个路径)。算法的主要部分完成后,您可以按照此反向引用重构路径。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-25
    • 1970-01-01
    • 1970-01-01
    • 2020-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多