蛇能获得的最大增长值

589 阅读2分钟

「这是我参与2022首次更文挑战的第4天,活动详情查看:2022首次更文挑战」。

给定一个矩阵matrix,值有正、负、0。蛇可以空降到最左列的任何一个位置,初始增长值是0。蛇每一步可以选择右上、右、右下三个方向的任何一个前进。沿途的数字累加起来,作为增长值;但是蛇一旦增长值为负数,就会死去。蛇有一种能力,可以使用一次:把某个格子里的数变成相反数。蛇可以走到任何格子的时候停止。返回蛇能获得的最大增长值。

一、分析

f(i,j)

初步分析:蛇从最优的最左边到达某个位置时,获得的最大增长值,在每个点上获得值求max

进一步分析:蛇有一种能力,是否使用这种能力。

f(i,j):返回两个值

  1. 蛇从最优的某个左侧位置开始,走到(i,j)位置停,中途一次也没用这种能力,获得的最大增长值
  2. 蛇从最优的某个左侧位置开始,走到(i,j)位置停,中途使用了一次这种能力,获得的最大增长值

最终答案:max(2*M*N) M*N的格子,每个格子返回2种答案,最后求Max

尝试模型

左上、左边、左下 => 当前位置,从三种情况下蛇可以到达当前位置

左边所有可能性中一次能力也没用和用了一次能力的最好情况

如果蛇从某一个最左列,且最优的空降点降落,不用能力,怎么都到不了(i,j),那么no = -1

如果蛇从某一个最左列,且最优的空降点降落,用了一次能力,怎么都到不了(i,j),那么yes = -1

当前的no:你之前并且你现在一次能力也没用

当前的yes:之前用了或者当前用,这两种情况

二、实现

public static int walk(int[][] matrix) {
    if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
        return 0;
    }
    int ans = 0;
    for (int i = 0; i < matrix.length; i++) {
        for (int j = 0; j < matrix[0].length; j++) {
            Info cur = f(matrix, i, j);
            ans = Math.max(ans, Math.max(cur.no, cur.yes));
        }
    }
    return ans;
}

public static class Info {
    public int no;
    public int yes;

    public Info(int n, int y) {
        no = n;
        yes = y;
    }
}

public static Info f(int[][] matrix, int i, int j) {
    if (j == 0) { // 最左列
        int no = Math.max(matrix[i][0], -1);
        int yes = Math.max(-matrix[i][0], -1);
        return new Info(no, yes);
    }
    // j > 0 不在最左列
    int preNo = -1;
    int preYes = -1;
    Info pre = f(matrix, i, j - 1);
    preNo = Math.max(pre.no, preNo);
    preYes = Math.max(pre.yes, preYes);
    if (i > 0) {
        pre = f(matrix, i - 1, j - 1);
        preNo = Math.max(pre.no, preNo);
        preYes = Math.max(pre.yes, preYes);
    }
    if (i < matrix.length - 1) {
        pre = f(matrix, i + 1, j - 1);
        preNo = Math.max(pre.no, preNo);
        preYes = Math.max(pre.yes, preYes);
    }
    int no = preNo == -1 ? -1 : (Math.max(-1, preNo + matrix[i][j]));
    // 能力只有一次,是之前用的!
    int p1 = preYes == -1 ? -1 : (Math.max(-1, preYes + matrix[i][j]));
    // 能力只有一次,就当前用!
    int p2 = preNo == -1 ? -1 : (Math.max(-1, preNo - matrix[i][j]));
    int yes = Math.max(Math.max(p1, p2), -1);
    return new Info(no, yes);
}

三、总结

感觉写代码跟咬文嚼字似的,你怎么假设的,就怎么写,代码就写出来了!