动态规划 矩阵中蛇能走的最大累加和

103 阅读1分钟

题目

image.png

  • 因为每一个点都可能产生最大值,所以遍历模型为可以往前遍历取上中下的遍历结果,之前位置的结果需要返回用过一次能力和一次能力都没用的结果,本位置根据上次结果来判断用能力和不用能力的结果然后返回
  • 本题提供了一种往前遍历的模型,以及递归中怎么实现之前用过了,后序都不能用的情况:把之前用过和没有过的情况都返回给后面
function snake(arr) {
  let maxSum = 0;
  for (let row = 0; row < arr.length; row++) {
    for (let col = 0; col < arr[0].length; col++) {
      // 拿到每一个点到之前路径的累加和 (一次能力也不用和用过一次能力的情况下)
      const info = process(arr, row, col);
      maxSum = Math.max(maxSum, Math.max(info.no, info.yes));
    }
  }

  function process(arr, row, col) {
    // 第一列的情况
    if (col == 0) {
      return { no: arr[row][col], yes: -arr[row][col] };
    }

    // 之前路径使用和没有能力的累加和
    let preNo = 0,
      preYes = 0;

    // 往前取左上角信息的情况
    // 不在第一行,也不在第一列
    if (row > 0) {
      let leftUp = process(arr, row - 1, col - 1);
      if (leftUp.no >= 0) {
        preNo = leftUp.no;
      }
      if (leftUp.yes >= 0) {
        preYes = leftUp.yes;
      }
    }

    // 往前取左边的位置
    let left = process(arr, row, col - 1);
    if (left.no >= 0) {
      preNo = Math.max(preNo, left.no);
    }
    if (left.yes >= 0) {
      preYes = Math.max(preYes, left.yes);
    }

    // 往前取左下的位置
    if (row < arr.length - 1) {
      let leftDown = process(arr, row + 1, col - 1);
      if (leftDown.no >= 0) {
        preNo = Math.max(preNo, leftDown.no);
      }
      if (leftDown.yes >= 0) {
        preYes = Math.max(preYes, leftDown.yes);
      }
    }

    // 构造自身返回值
    let yes = 0,
      no = 0;
    if (preNo >= 0) {
      // 之前没用能力+当前也不用的情况
      no = preNo + arr[row][col];
      // 之前没有用过+当前用能力;
      yes = preNo - arr[row][col];
    }
    // 之前用过+现在不能用;
    if (preYes >= 0) {
      no = Math.max(no, preYes + arr[row][col]);
    }

    return { yes, no };
  }
}