当前位置: 首页 > 知识库问答 >
问题:

如何加快/修复此最短路径网格遍历?

公羊瀚
2023-03-14

我正在编写一个程序,从左下角到右上角遍历网格,其中有效移动是向右移动1,向上移动1,或向上或向右跳跃跳跃跳跃数组中指定的数量。输入是2D数组格式的网格、网格的尺寸:X和Y,以及必须按顺序完成跳转的跳转数组。输出是最短路径,其中路径的长度是所有接触的数字的总和,包括左下角和右上角
示例输入:

Grid: 
    [9 9 1]
    [9 9 1]    
    [3 9 1]

Jumps: [1 1] X:3, Y:3

输出是5,因为我们从(0,0)开始,它是3,然后使用第一个1块跳转到(2,0),它是1,然后第二个1块跳转到(2,2),它是1,所以3 1 1=5.如果跳跃数组只有[1],那么输出将是6,因为我们必须从(2,0)到(2,1)再到(2,2)。

这是我的第一个解决方案,它似乎适用于较小的输入,但只适用于较大的输入:

def get(grid, x, y, endX, endY):
    if (x > endX or y > endY):
        return False
    return grid[y][x]

def fly(x, y, grid, jumps, endX, endY):
    if x > endX or y > endY:
        return float('inf')
    if (x == endX and y == endY):
        return get(grid, endX, endY, endX, endY)
    flyup = fly(x, y+1, grid, jumps, endX, endY)
    flyright = fly(x+1, y, grid, jumps, endX, endY)
    if (len(jumps) > 0):
        jumpup = fly(x, y+jumps[0]+1, grid, jumps[1:], endX, endY)
        jumpright = fly(x+jumps[0]+1, y, grid, jumps[1:], endX, endY)
        temp = min(flyup, flyright, jumpup, jumpright)
        return get(grid, x, y, endX, endY) + temp
    else:
        temp = min(flyup, flyright)
        return get(grid, x, y, endX, endY) + temp

fly(0, 0, grid, jumps, X-1, Y-1)

这是我用DP写的另一个解决方案(或者我刚学DP时对DP的理解是什么),但这个解决方案似乎只适用于某些输入,我无法识别模式

def fly2(x, y, grid, jumps):
    dp = [[0 for i in range(len(grid[0]))] for j in range(len(grid))]
    for row in range(len(grid)):
        for col in range(len(grid[0])):
            if row == 0 and col == 0:
                dp[row][col] += get2(grid, col, row)
            else:
                flyup = float('inf') if row==0 else dp[row-1][col]
                flyright = float('inf') if col==0 else dp[row][col-1]
                jumpup =  float('inf') if row < jumps[0]+1 else dp[row-jumps[0]-1][col]
                jumpright =  float('inf') if col < jumps[0]+1 else dp[row][col-jumps[0]-1]
                shortest = min(flyup, flyright, jumpup, jumpright)
                if min == jumpup or min == jumpright:
                    jumps = jumps[1:]
                dp[row][col] += get2(grid, col, row) + shortest
    return dp[len(grid)-1][len(grid[0])-1]

我需要一些帮助来加快第一个,或者找出第二个有什么问题,或者也许得到一些关于如何有效地写这个的其他想法。谢啦

共有2个答案

梁昊天
2023-03-14

以下实现使用网格和剩余的跳跃作为状态变量:

import numpy as np

def shortest(grid, jumps):
    rows, cols = grid.shape
    if (rows, cols) == (1, 1): # if grid is just a single number
        return float('inf') if jumps else grid[0, 0]
    candidates = [] # store results from deeper calls
    if rows > 1:
        candidates.append(shortest(grid[:-1, :], jumps)) # up by one
        if jumps and rows > jumps[0] + 1: # jump to the above if possible
            candidates.append(shortest(grid[:-(jumps[0] + 1), :], jumps[1:]))
    if cols > 1:
        candidates.append(shortest(grid[:, 1:], jumps)) # right by one
        if jumps and cols > jumps[0] + 1: # jump to the right if possible
            candidates.append(shortest(grid[:, (jumps[0] + 1):], jumps[1:]))
    return grid[-1, 0] + min(candidates)

grid = np.array([[9, 9, 1], [9, 9, 1], [3, 9, 1]])
jumps = [1, 1]
print(shortest(grid, jumps)) # 5

使用np.array只是为了简化切片。

贺浩漫
2023-03-14

在我看来,dp对于当前的跳跃指数应该有另一个维度。通常地

dp[y][x][j] = Grid[y][x] + min(
  dp[y + 1][x][j],
  dp[y][x - 1][j],
  dp[y + jump[j-1] + 1][x][j-1],
  dp[y][x - jump[j-1] - 1][j-1]
)

其中j是跳转数组中的当前索引。

(我认为问题描述在例子中使用了(x,y)坐标表示法。我使用[y][x]作为[行][列],常用于编程二维数组访问。(

 类似资料:
  • 主要内容:src/runoob/graph/ShortestPath.java 文件代码:广度优先遍历从某个顶点 v 出发,首先访问这个结点,并将其标记为已访问过,然后顺序访问结点v的所有未被访问的邻接点 {vi,..,vj} ,并将其标记为已访问过,然后将 {vi,...,vj} 中的每一个节点重复节点v的访问方法,直到所有结点都被访问完为止。 我们可以分为三个步骤: (1)使用一个辅助队列 q,首先将顶点 v 入队,将其标记为已访问,然后循环检测队列是否为空。 (2)如果队列不为空

  • 主要内容:最短路径算法在给定的图存储结构中,从某一顶点到另一个顶点所经过的多条边称为 路径。 图 1 图存储结构 例如在图 1 所示的图结构中,从顶点 A 到 B 的路径有多条,包括 A-B、A-C-B 和 A-D-B。当我们给图中的每条边赋予相应的权值后,就可以从众多路径中找出总权值最小的一条,这条路径就称为 最短路径。 图 2 无向带权图 以图 2 为例,从顶点 A 到 B 的路径有 3 条,它们各自的总权值是:

  • 我有一个一般性的问题,关于如何在边没有权的无向图中找到最短路径和最长路径。 我们需要使用DFS算法来寻找图中的最长路径,而我们需要使用BFS算法来寻找图中的最短路径,这是一个正确的结论吗?

  • 当你在网上冲浪,发送电子邮件,或从校园的另一个地方登录实验室计算机时,大量的工作正在幕后进行,以获取你计算机上的信息传输到另一台计算机。 深入研究信息如何通过互联网从一台计算机流向另一台计算机是计算机网络中的一个主要课题。 然而,我们将讨论互联网如何工作足以理解另一个非常重要的图算法。 Figure 1 Figure 1 展示了 Internet 上的通信如何工作的高层概述。当使用浏览器从服务器请

  • 我们有一个边带正权的有向图G(V,E),作为源顶点s,目标点T。此外,最短的s-t路径包括图中的每一个其他顶点。我需要计算s和t之间的交替最短路径距离,以防某些边e∈e被删除。我想设计一个O(e^2logV)算法,它计算图G\e中所有e∈e的最短S-T路径距离。最后的输出应该是一个大小为E的数组,其中edge E的条目应该包含G\E中最短的S-T路径距离。

  • 在一个加权有向图中,我需要找到两个结点s,t之间的最短路径。以下是限制: 权重可以为负值。 路径必须经过一个特定的边,让我们从节点u到V调用her e和shes。 输出路径必须简单,即我们只通过一个节点一次。 因为我希望它最短,所以我将检查在从s到u之前从v到t运行bellman ford是否比相反的方式更快(如果有节点,两个节点都使用where是放置它的最佳位置)。 谢谢你的帮助!