|
|
package class08;
|
|
|
|
|
|
import java.util.Arrays;
|
|
|
|
|
|
public class Code04_SnakeGame {
|
|
|
|
|
|
public static int walk1(int[][] matrix) {
|
|
|
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
|
|
|
return 0;
|
|
|
}
|
|
|
int res = Integer.MIN_VALUE;
|
|
|
for (int i = 0; i < matrix.length; i++) {
|
|
|
for (int j = 0; j < matrix[0].length; j++) {
|
|
|
int[] ans = process(matrix, i, j);
|
|
|
res = Math.max(res, Math.max(ans[0], ans[1]));
|
|
|
}
|
|
|
}
|
|
|
return res;
|
|
|
}
|
|
|
|
|
|
public static int zuo(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;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 蛇从某一个最左列,且最优的空降点降落
|
|
|
// 沿途走到(i,j)必须停!
|
|
|
// 返回,一次能力也不用,获得的最大成长值
|
|
|
// 返回,用了一次能力,获得的最大成长值
|
|
|
// 如果蛇从某一个最左列,且最优的空降点降落,不用能力,怎么都到不了(i,j),那么no = -1
|
|
|
// 如果蛇从某一个最左列,且最优的空降点降落,用了一次能力,怎么都到不了(i,j),那么yes = -1
|
|
|
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);
|
|
|
}
|
|
|
|
|
|
// 从假想的最优左侧到达(i,j)的旅程中
|
|
|
// 0) 在没有使用过能力的情况下,返回路径最大和,没有可能到达的话,返回负
|
|
|
// 1) 在使用过能力的情况下,返回路径最大和,没有可能到达的话,返回负
|
|
|
public static int[] process(int[][] m, int i, int j) {
|
|
|
if (j == 0) { // (i,j)就是最左侧的位置
|
|
|
return new int[] { m[i][j], -m[i][j] };
|
|
|
}
|
|
|
int[] preAns = process(m, i, j - 1);
|
|
|
// 所有的路中,完全不使用能力的情况下,能够到达的最好长度是多大
|
|
|
int preUnuse = preAns[0];
|
|
|
// 所有的路中,使用过一次能力的情况下,能够到达的最好长度是多大
|
|
|
int preUse = preAns[1];
|
|
|
if (i - 1 >= 0) {
|
|
|
preAns = process(m, i - 1, j - 1);
|
|
|
preUnuse = Math.max(preUnuse, preAns[0]);
|
|
|
preUse = Math.max(preUse, preAns[1]);
|
|
|
}
|
|
|
if (i + 1 < m.length) {
|
|
|
preAns = process(m, i + 1, j - 1);
|
|
|
preUnuse = Math.max(preUnuse, preAns[0]);
|
|
|
preUse = Math.max(preUse, preAns[1]);
|
|
|
}
|
|
|
// preUnuse 之前旅程,没用过能力
|
|
|
// preUse 之前旅程,已经使用过能力了
|
|
|
int no = -1; // 之前没使用过能力,当前位置也不使用能力,的最优解
|
|
|
int yes = -1; // 不管是之前使用能力,还是当前使用了能力,请保证能力只使用一次,最优解
|
|
|
if (preUnuse >= 0) {
|
|
|
no = m[i][j] + preUnuse;
|
|
|
yes = -m[i][j] + preUnuse;
|
|
|
}
|
|
|
if (preUse >= 0) {
|
|
|
yes = Math.max(yes, m[i][j] + preUse);
|
|
|
}
|
|
|
return new int[] { no, yes };
|
|
|
}
|
|
|
|
|
|
public static int walk2(int[][] matrix) {
|
|
|
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
|
|
|
return 0;
|
|
|
}
|
|
|
int max = Integer.MIN_VALUE;
|
|
|
int[][][] dp = new int[matrix.length][matrix[0].length][2];
|
|
|
for (int i = 0; i < dp.length; i++) {
|
|
|
dp[i][0][0] = matrix[i][0];
|
|
|
dp[i][0][1] = -matrix[i][0];
|
|
|
max = Math.max(max, Math.max(dp[i][0][0], dp[i][0][1]));
|
|
|
}
|
|
|
for (int j = 1; j < matrix[0].length; j++) {
|
|
|
for (int i = 0; i < matrix.length; i++) {
|
|
|
int preUnuse = dp[i][j - 1][0];
|
|
|
int preUse = dp[i][j - 1][1];
|
|
|
if (i - 1 >= 0) {
|
|
|
preUnuse = Math.max(preUnuse, dp[i - 1][j - 1][0]);
|
|
|
preUse = Math.max(preUse, dp[i - 1][j - 1][1]);
|
|
|
}
|
|
|
if (i + 1 < matrix.length) {
|
|
|
preUnuse = Math.max(preUnuse, dp[i + 1][j - 1][0]);
|
|
|
preUse = Math.max(preUse, dp[i + 1][j - 1][1]);
|
|
|
}
|
|
|
dp[i][j][0] = -1;
|
|
|
dp[i][j][1] = -1;
|
|
|
if (preUnuse >= 0) {
|
|
|
dp[i][j][0] = matrix[i][j] + preUnuse;
|
|
|
dp[i][j][1] = -matrix[i][j] + preUnuse;
|
|
|
}
|
|
|
if (preUse >= 0) {
|
|
|
dp[i][j][1] = Math.max(dp[i][j][1], matrix[i][j] + preUse);
|
|
|
}
|
|
|
max = Math.max(max, Math.max(dp[i][j][0], dp[i][j][1]));
|
|
|
}
|
|
|
}
|
|
|
return max;
|
|
|
}
|
|
|
|
|
|
public static int[][] generateRandomArray(int row, int col, int value) {
|
|
|
int[][] arr = new int[row][col];
|
|
|
for (int i = 0; i < arr.length; i++) {
|
|
|
for (int j = 0; j < arr[0].length; j++) {
|
|
|
arr[i][j] = (int) (Math.random() * value) * (Math.random() > 0.5 ? -1 : 1);
|
|
|
}
|
|
|
}
|
|
|
return arr;
|
|
|
}
|
|
|
|
|
|
public static void main(String[] args) {
|
|
|
int N = 7;
|
|
|
int M = 7;
|
|
|
int V = 10;
|
|
|
int times = 1000000;
|
|
|
for (int i = 0; i < times; i++) {
|
|
|
int r = (int) (Math.random() * (N + 1));
|
|
|
int c = (int) (Math.random() * (M + 1));
|
|
|
int[][] matrix = generateRandomArray(r, c, V);
|
|
|
int ans1 = zuo(matrix);
|
|
|
int ans2 = walk2(matrix);
|
|
|
if (ans1 != ans2) {
|
|
|
for (int j = 0; j < matrix.length; j++) {
|
|
|
System.out.println(Arrays.toString(matrix[j]));
|
|
|
}
|
|
|
System.out.println("Oops ans1: " + ans1 + " ans2:" + ans2);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
System.out.println("finish");
|
|
|
}
|
|
|
|
|
|
}
|