代码之家  ›  专栏  ›  技术社区  ›  Pasha

如何在矩阵中用最小和计算从[0,0]到[M,N]的路径?

  •  1
  • Pasha  · 技术社区  · 5 年前

    我需要计算从[0,0]到[M,N]的路径,矩阵中的最小和只向右或向下移动?

    我发现了这种联系 https://www.programcreek.com/2014/05/leetcode-minimum-path-sum-java/ 但动态编程选项一点也不清楚。

    我试着用BFS算法自己实现它,但这是一个缓慢的解决方案

    public int minPathSum(final int[][] grid) {
            if (grid.length == 1 && grid[0].length == 1) {
                return grid[0][0];
            }
            final int[][] moves = {new int[]{1, 0}, new int[]{0, 1}};
            final Queue<int[]> positions = new ArrayDeque<>();
            final Queue<Integer> sums = new ArrayDeque<>();
            positions.add(new int[]{0, 0});
            sums.add(grid[0][0]);
            int minSum = Integer.MAX_VALUE;
            while (!positions.isEmpty()) {
                final int[] point = positions.poll();
                final int sum = sums.poll();
                for (final int[] move : moves) {
                    final int x = point[0] + move[0];
                    final int y = point[1] + move[1];
                    if (x == grid.length - 1 && y == grid[0].length - 1) {
                        minSum = Math.min(minSum, sum);
                    } else if (x > -1 && y > -1 && x < grid.length && y < grid[0].length) {
                        positions.add(new int[]{x, y});
                        sums.add(sum + grid[x][y]);
                    }
                }
            }
            return minSum + grid[grid.length - 1][grid[0].length - 1];
        }
    

    请你解释一下,如果可能的话,请提供你将如何解决这个问题?

    2 回复  |  直到 5 年前
        1
  •  2
  •   גלעד ברקן    5 年前

    对于如何实现广度优先搜索,我有点困惑,但在理解这里的动态公式时遇到了困难,在我看来更简单:)

    这几乎是经典的动态规划问题。到达任何一个牢房, solution[y][x] ,除第一个外,最多有两个前置任务: option 1 option 2 . 假设我们知道达到这些目标的最佳解决方案,我们会选择哪条边?显然,这两个选择中最好的一个!

    稍微正式一点,如果 M 保持给定值:

    solution[0][0] = M[0][0]
    
    // only one choice along
    // the top horizontal and
    // left vertical
    
    solution[0][x] =
      M[0][x] + solution[0][x - 1]
    
    solution[y][0] =
      M[y][0] + solution[y - 1][0]
    
    // two choices otherwise:
    // the best of option 1 or 2
    
    solution[y][x] =
      M[y][x] + min(
        solution[y][x - 1],
        solution[y - 1][x]
      )
    

    我们可以看到我们可以创建一个适当的例程 for 例如,访问 solution 矩阵的“自底向上”顺序,因为每个单元格的值取决于我们已经计算过的一个或两个前置值。

    JavaScript代码:

    function show(M){
      let str = '';
      for (let row of M)
        str += JSON.stringify(row) + '\n';
      console.log(str);
    }
    
    function f(M){
      console.log('Input:\n');
      show(M);
      
      let solution = new Array();
      for (let i=0; i<M.length; i++)
        solution.push(new Array(M[0].length).fill(Infinity));
        
      solution[0][0] = M[0][0];
    
      // only one choice along
      // the top horizontal and
      // left vertical
      
      for (let x=1; x<M[0].length; x++)
        solution[0][x] =
          M[0][x] + solution[0][x - 1];
    
      for (let y=1; y<M.length; y++)
        solution[y][0] =
          M[y][0] + solution[y - 1][0];
          
      console.log('Solution borders:\n');
      show(solution);
    
      // two choices otherwise:
      // the best of option 1 or 2
    
      for (let y=1; y<M.length; y++)
        for (let x=1; x<M[0].length; x++)
          solution[y][x] =
            M[y][x] + Math.min(
              solution[y][x - 1],
              solution[y - 1][x]
            );
            
      console.log('Full solution:\n');
      show(solution);
      
      return solution[M.length-1][M[0].length-1];
    }
    
    let arr = [];
    arr[0] = [0, 7, -7];
    arr[1] = [6, 7, -8];
    arr[2] = [1, 2, 0];
    
    console.log(f(arr));
        2
  •  0
  •   iddqd    5 年前

    到达(m,n)的路径必须通过两个单元格之一:(m-1,n)或(n-1,m)。所以最小和(m,n)可以写成2个单元格的最小值加上和[m][n]。

    minSum(m, n) = min (minSum(m-1, n-1), minSum(m-1, n)) + sums[m][n]