【问题标题】:Dynamic Programming find max path with constraints in 2D array动态规划在二维数组中找到具有约束的最大路径
【发布时间】:2021-05-04 06:05:42
【问题描述】:

您好,我在 dp 有一个问题,如下所示:

输入:二维数字数组

输出:从 (0,0) 到 (n-1,n-1) 的路径的最大总和,其中需要满足这两个条件:

  1. 只能向下向右移动意思:

    (A[i-1][j]) --> (A[i][j]) 或 (A[i][j-1]) --> (A[i][j])

  2. 你不能在一行中水平移动 3 次

到目前为止我的代码:


export default (arr: Array<Array<number>>) => {

    let B: Array<Array<{ info: number, rightCount: number }>> = init2DArr(arr.length, arr[0].length) // when 
    B[0][0] = { info: arr[0][0], rightCount: 0 };

    for (let i = 1; i < arr.length; i++) {
        B[0][i] = { info: (arr[0][i] + B[0][i - 1].info), rightCount: i };
        B[i][0] = { info: (arr[i][0] + B[i - 1][0].info), rightCount: 0 };
    }
    for (let i = 1; i < arr.length; i++) {
        for (let j = 1; j < arr.length; j++) {
            if(B[i-1][j].rightCount >= 3){
                B[i][j] = { info: arr[i][j] + B[i][j - 1].info, rightCount: B[i][j - 1].rightCount + 1 }
                continue;
            }

            if(B[i][j-1].rightCount == 2){
                B[i][j] = { info: arr[i][j] + B[i - 1][j].info, rightCount: 0 }
                continue;
            }

            if (B[i - 1][j].info >= B[i][j - 1].info) { // top
                B[i][j] = { info: arr[i][j] + B[i - 1][j].info, rightCount: 0 }
            }
            else if(B[i][j-1].info > B[i-1][j].info)
            {
                B[i][j] = { info: arr[i][j] + B[i][j - 1].info, rightCount: B[i][j - 1].rightCount + 1 }
            }
        }
    }
    console.log(B[arr.length - 1][arr.length - 1].info)
}



const init2DArr = (n: number, m: number) => {
    let res = Array(n);
    for (let i = 0; i < res.length; i++) {
        res[i] = Array(m)
    }
    return res;
}


但是这段代码并不完整,因为对于这个输入:


getMaxPath([[1,1,1,1],
            [7,9,4,2000],
            [6,22,1,1],
            [1,1,1,1]])

2000 不包含在路径中,即使路径:

1 -> 1 -> 9 -> 4 -> 2000 -> 1 -> 1

显然是最大值。

因此代码应该返回 2017(路径的总和)。

意思是我的代码没有对所有可能的路径进行评估。 任何帮助将不胜感激

【问题讨论】:

  • 只是一个问题,还需要检查是否真的相关,数组中是否允许负数?
  • 是的,允许负数
  • 为什么不1 1 9 4 2000 1 1
  • @NinaScholz 见规则 2
  • 但是为什么1 1 1

标签: javascript node.js arrays typescript algorithm


【解决方案1】:

这里是动态规划的实现,它处理每一行,探索在下降之前水平移动的单元格可以达到的最大值。

<script>
  function getMaxPath(arr) {
    var currentRow = [{
      sum: 0,
      path: []
    }];
    for (var i = 0; i < arr.length; i++) {
      var row = arr[i];
      var nextRow = new Array();
      for (var j = 0; j < currentRow.length; j++) {
        var sum = currentRow[j].sum;
        var path = currentRow[j].path.slice();
        for (var k = 0; k <= 2 && j + k < row.length; k++) {
          sum += row[j + k];
          path.push(row[j + k]);
          if (j + k >= nextRow.length) {
            nextRow.push({ sum: sum, path: path.slice() });
          } else {
            if (sum > nextRow[j + k].sum) {
              nextRow[j + k] = { sum: sum, path: path.slice() };
            }
          }
        }
      }
      currentRow = nextRow;
    }
    return currentRow[currentRow.length - 1];
  }
  console.log(getMaxPath([
    [1, 1, 1, 1],
    [7, 9, 4, 2000],
    [6, 22, 1, 1],
    [1, 1, 1, 1]
  ]));
</script>

【讨论】:

    【解决方案2】:

    您可以采用蛮力方法,获取所有可能且有效的路径,然后选择总和最大的路径。

    function getMaxPath(matrix) {
        const
            sum = array => array.reduce((a, b) => a + b),
            stack = [[0, 0, '', 0, []]],
            pathes = [];
    
        while (stack.length) {
            const [i, j, dir, count, [...path]] = stack.shift();
            path.push(matrix[i][j]);
            if (i === matrix.length - 1 && j === matrix[i].length - 1) {
                pathes.push(path);
                continue;
             }
            
            if (i + 1 < matrix.length && (dir !== 'down' || count < 2)) {
                stack.push([i + 1, j, 'down', dir === 'down' ? count + 1 : 1, path]);
            }
            
            if (j + 1 < matrix[i].length && (dir !== 'right' || count < 2)) {
                stack.push([i, j + 1, 'right', dir === 'right' ? count + 1 : 1, path]);
            }
        }
        return pathes.reduce((a, b) => sum(a) > sum(b) ? a : b);
    }
    
    console.log(...getMaxPath([[1, 1, 1, 1], [7, 9, 4, 2000], [6, 22, 1, 1], [1, 1, 1, 1]]));

    【讨论】:

      【解决方案3】:

      典型的自下而上的动态程序会使用除ij 之外的第三种状态。像[i][j][num_moves] 一样,空间需求翻倍。但是您的代码不允许每个 (i, j) 组合有多个同时移动计数状态。尝试使用dp[i][j][num_moves] 制定递归。

      【讨论】:

        猜你喜欢
        • 2021-12-23
        • 1970-01-01
        • 2020-09-19
        • 1970-01-01
        • 1970-01-01
        • 2012-07-11
        • 2017-08-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多