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

使用向右或向下跳跃或单位步数在网格中的最小成本路径

公孙成仁
2023-03-14

假设您有一个网格,其中每个节点都包含一个权重,该权重表示获取该正方形的成本。

从二维数组左上角的(0,0)开始,然后到达(X-1,Y-1),其中X是列数,Y是右下角的行数。你可以向右走1平方米,也可以一次向下走1平方米。您还将获得一个整数“跳跃”数组,其中每个值$d_i$表示您可以在第i次跳跃时向右或向下跳过的方块数。跳转数组指定跳转的顺序,这意味着,例如,如果没有使用一个跳转,则不能跳转[2]。您只能进行len(jump)次跳跃。

我们正试图用动态规划来解决这个问题。这就是我迄今为止所做的:

def helper(grid, jumps):
    dCount = 0
    dp = [[[0 for k in range(len(jumps)+1)] for j in  range(len(grid[0]))] for i 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][dCount] += grid[row][col]
            jumpRight = float('infinity')
            jumpUp = float('infinity')
            goUp = float('infinity')
            goRight = float('infinity')
            if(row > 0):
                goUp = dp[row-1][col][dCount]
            if(col > 0):
                goRight = dp[row][col-1][dCount]
            if (dCount < len(jumps)):
                jumpRight = dp[row-jumps[dCount]][col][dCount] 
                jumpUp = dp[row][col-jumps[dCount]][dCount]
            res = grid[row][col] + min(goRight, goUp, jumpRight, jumpUp)
            if(res == jumpRight or res==jumpUp): 
                dCount+=1
            dp[row][col][dCount] = res
    return dp[len(grid)-1][len(grid[0])-1]

grid = [[1, 0, 3, 7, 2, 5], [8, 3, 7, 6, 9, 8], [9, 7, 8, 2, 1, 1], [3, 2, 9, 1, 7, 8]]

jumps = [1, 1]
print(helper(grid,jumps)) #should be 16

然而,代码似乎不起作用。

上面只是打印出[0 0 15],而我认为应该是[0 0 16]

共有2个答案

颜镜
2023-03-14

下面是一个自底向上方法的示例,它似乎返回了本例和类似问题中的正确结果。不过,我不确定代码是否万无一失。

Python:

def f(grid, jumps):
  m, n = len(grid), len(grid[0])
  dp = [None] * m

  for i in range(m):
    dp[i] = [[float('inf')] * (len(jumps) + 1) for j in range(n)]

  dp[0][0][0] = grid[0][0]

  for y in range(m):
    for x in range(n):
      for j in range(len(jumps) + 1):
        if (y, x, j) == (0, 0, 0):
          continue

        dp[y][x][j] = grid[y][x] + min(
          dp[y - 1][x][j] if y > 0 else float('inf'),
          dp[y][x - 1][j] if x > 0 else float('inf'),
          dp[y - jumps[j-1] - 1][x][j-1] if (j > 0 and y - jumps[j-1] - 1 >= 0) else float('inf'),
          dp[y][x - jumps[j-1] - 1][j-1] if (j > 0 and x - jumps[j-1] - 1 >= 0) else float('inf')
        )
  
  return min(dp[m-1][n-1])


grid = [
  [1, 0, 3, 7, 2, 5],
  [8, 3, 7, 6, 9, 8],
  [9, 7, 8, 2, 1, 1],
  [3, 2, 9, 1, 7, 8]]

jumps = [1, 1]

print(f(grid, jumps)) # 16


grid = [
  [3, 9, 1],
  [9, 9, 1],
  [9, 9, 1]
]

jumps = [1, 1]

print(f(grid, jumps)) # 5
岳出野
2023-03-14

以下是一个实施方案:

def shortest(grid, jumps, x=0, y=0, jumped=0):
    # grid: whole grid
    # jumps: jumps to be exhuasted
    # x, y: current position
    # jumped: number of jumps that have been used
    # output: a tuple (cost, path)
    #         cost: minimum cost from this position to the final position
    #         path: a list of tuples, each element the position along the minimum-cost path
    rows = len(grid) - x; cols = len(grid[0]) - y # remaining num of rows and cols
    if (rows, cols) == (1, 1): # if arrived at the southeast corner
        return (float('inf'), [(x, y)]) if jumps[jumped:] else (grid[x][y], [(x, y)]) # return inf if jumps are not exhausted
    candidates = [] # store results from deeper calls
    if rows > 1: # if possible to move down
        candidates.append(shortest(grid, jumps, x+1, y, jumped)) # down by one
        if jumped < len(jumps) and rows > jumps[jumped] + 1: # if possible to jump
            candidates.append(shortest(grid, jumps, x+jumps[jumped]+1, y, jumped+1)) # jump down
    if cols > 1: # if possible to move right
        candidates.append(shortest(grid, jumps, x, y+1, jumped)) # right by one
        if jumped < len(jumps) and cols > jumps[jumped] + 1: # if possible to jump
            candidates.append(shortest(grid, jumps, x, y+jumps[jumped]+1, jumped+1)) # jump right
    temp = min(candidates, key=lambda x: x[0]) # recall: temp[0]: min_cost, temp[1]: min_path
    return (temp[0] + grid[x][y], [(x, y), *temp[1]])

grid = [[1, 0, 3, 7, 2, 5], [8, 3, 7, 6, 9, 8], [9, 7, 8, 2, 1, 1], [3, 2, 9, 1, 7, 8]]

jumps = [1, 1]
print(shortest(grid, jumps)) # (16, [(0, 0), (0, 1), (0, 2), (0, 4), (2, 4), (2, 5), (3, 5)])

状态变量是xy跳转xy记住当前位置在给定网格中的位置。跳转记住有多少次跳转到目前为止使用。

递归的结束状态发生在位置位于最终目的地时,即[-1,-1]。如果跳跃尚未用尽,则为失败;因此,返回无穷大作为代价。否则,返回该点的值作为成本。

实际上,返回是一个元组;第一个元素是成本,第二个元素是当前位置。第二个元素用于最终获得成本最小化路径。

在其他状态下,递归是以自然的方式定义的;该函数递归为(最多)四种可能的移动:向上移动一次,向右移动一次,向上跳,向右跳。它比较结果成本,并选择最小成本方向。

注意:这使用了python 3.5中引入的通用解包。但这并不重要。

 类似资料:
  • 问题陈述:给定一个长度为N的非负整数数组A,您最初位于数组的第一个索引处。数组中的每个元素表示该位置的最大跳跃长度。返回到达最后一个索引所需的最小跳转次数。 输入:A=[2,3,1,1,4] 产出:2 说明:达到指数4的最短途径是指数0- 以下是解决方案: 我得到了上述解决方案的TLE。我无法在记忆后计算出解决方案的时间复杂度。有人能帮我估计一下上述解决方案的时间复杂度吗。

  • 我得到了一个n乘n的字符网格和一个字符串。我想找到一条路径(n中(I,j)对的序列),这样它们就形成了一条拼出s的路径。我可以从网格中的任何地方开始,但我只能在网格中向右或向下移动一步。 解决这个问题的有效方法是什么?我看了一个类似的问题,你可以在各个方向移动。但是,既然我们只能向右或向下移动,我们还能改进什么呢?

  • 我在垂直列中构建了一个相当正常的菜单-子菜单排列--嵌套的ULs,使用展开和折叠子菜单。 我想要解决的问题是子菜单在最后“跳”开的方式。(我正在Chrome的最新版本中进行测试。)它可能在第二个子菜单“福利”中最引人注目。它不会在菜单折叠时跳转,只有在菜单展开时才跳转。 我认为问题可能与样式有关,只有在菜单完全展开时才添加。具体地说,一旦菜单完全展开,类就会添加到LI标记中。但注释掉切换该类的代码

  • 下面是寻找最小跳跃次数的算法谜题。发布了详细的问题声明和两个代码版本来解决这个问题。我做了测试,似乎两个版本都可以工作,我的第二个版本是版本一代码的优化版本,这使得我从开始,而不是持续增加,这可以通过不迭代所有的插槽来节省时间数组。 我的问题是,想知道我的第二个版本代码是否100%正确?如果有人发现任何逻辑问题,请指出。 问题陈述 给定一个非负整数数组,您最初位于数组的第一个索引处。 数组中的每个

  • 是否可以以与选项类似的方式处理任一选项?在

  • 我在Selenium 1(又名Selenium RC)中编写了以下代码,用于使用java滚动页面: Selenium 2(WebDriver)中的等效代码是什么?