题目
- 因为每一个点都可能产生最大值,所以遍历模型为可以往前遍历取上中下的遍历结果,之前位置的结果需要返回用过一次能力和一次能力都没用的结果,本位置根据上次结果来判断用能力和不用能力的结果然后返回
- 本题提供了一种往前遍历的模型,以及递归中怎么实现之前用过了,后序都不能用的情况:把之前用过和没有过的情况都返回给后面
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 };
}
}