从左列到右列的最大路径总和

时间:2015-09-27 11:18:45

标签: algorithm data-structures graph dynamic-programming

我正在尝试计算从网格中的左列到右列可以实现的最大总和。允许的动作是向上,向下,向右。我已经实现了这个解决方案(它是广度优先搜索):

for(int i=1; i<=n; i++) {
    Queue<Position> q = new LinkedList<Position>();
    q.add(new Position(i, 1));
    dp[i][1] = map[i][1];

    while(!q.isEmpty()) {
        Position node = q.poll();
        visited[node.n][node.m] = 1;
        if(dp[node.n][node.m] > max) {
            max = dp[node.n][node.m];
        }
        if(visited[node.n-1][node.m] != 1 && node.n != 1 && dp[node.n-1][node.m] < dp[node.n][node.m] + map[node.n-1][node.m] && map[node.n-1][node.m] != -1) {
            dp[node.n-1][node.m] = dp[node.n][node.m] + map[node.n-1][node.m];  

            q.add(new Position(node.n-1, node.m));
        }
        if(visited[node.n+1][node.m] != 1 && node.n != n && dp[node.n +1][node.m] < dp[node.n][node.m] + map[node.n+1][node.m] && map[node.n+1][node.m] != -1) {
            dp[node.n +1][node.m] = dp[node.n][node.m] + map[node.n+1][node.m];
            q.add(new Position(node.n + 1, node.m));
        }
        if(visited[node.n][node.m+1] != 1 && node.m != m && dp[node.n][node.m+1] < dp[node.n][node.m] + map[node.n][node.m+1] && map[node.n][node.m+1] != -1) {
            dp[node.n][node.m+1] = dp[node.n][node.m] + map[node.n][node.m+1];
            q.add(new Position(node.n, node.m+1));
        }

    }
}
static class Position {
        int n, m;
        public Position(int row, int column) {
            this.n = row;
            this.m = column;
        }
    }

示例输入:

-1 4 5 1
2 -1 2 4
3 3 -1 3
4 2 1 2

我的解决方案的问题是它应该通过以下4-&gt; 3-&gt; 3-&gt; 2达到2(在最后一行第2列)但我的解决方案将2置于访问状态,因此它不会检查它。如果我删除被访问的数组,它将陷入任何单元格的向上,向下,向上,向下的无限循环。

修改:每个点只能访问一次。

1 个答案:

答案 0 :(得分:1)

这个问题可以通过线性编程方法解决,但是有一个小的转折,因为你不能多次访问每个单元格,但这些动作实际上可以带你到达那个条件。

要解决此问题,您可以注意到在给定位置(x, y)中您要么

  • 刚刚从(x, y)到达(x-1, y),因此您可以上下,上下行(当然,除非您处于边缘)
  • (x, y)(即从上方)到达(x, y-1),然后您只允许向下或向右
  • (x, y)(即从下方)到达(x, y+1),然后您只允许上升或右上

这直接转换为以下递归记忆解决方案(代码在Python中):

matrix = [[-1, 4, 5, 1],
          [ 2,-1, 2, 4],
          [ 3, 3,-1, 3],
          [ 4, 2, 1, 2]]
rows = len(matrix)
cols = len(matrix[0])
cache = {}

def maxsum(dir, x, y):
    key = (dir, x, y)
    if key in cache: return cache[key]
    base = matrix[y][x]
    if x < cols-1:
        best = base + maxsum("left", x+1, y)
    else:
        best = base
    if dir != "above" and y > 0:
        best = max(best, base + maxsum("below", x, y-1))
    if dir != "below" and y < rows-1:
        best = max(best, base + maxsum("above", x, y+1))
    cache[key] = best
    return best

print(max(maxsum("left", 0, y) for y in range(rows)))

如果不允许跳过负值(即使这样可以保证更大的总和),则更改很简单(如果没有路径从左列到右列,则需要指定返回的内容)