问题:给定一个矩阵matrix,矩阵中的value有正负还有0,贪吃蛇可以空降到最左侧的任何位置,初始增长值是0.蛇莓走一步可以选右上,右,右下三个方向的任何一个前进,沿途的数字累加起来,作为增长值;但是蛇一旦增长值为负数,就会死去。蛇有一种能力,可以使用一次;把某个格子里的数变成相反数,蛇可以走到任何格子的时候停止,返回蛇能获得的最大增长值。value
解决思想:创建Info类,保存使用技能最大值和不使用技能最大值。分三种情况讨论,i表示行,j表示列,当j==0时,当i>0时,和当i<matrix.length-1时分别对应在最左侧的情况,右上有值时,右下有值时。然后从不同位置出发比较出不同位置使用技能和不使用技能的最大值。
代码:
package shuait8;
import java.util.Arrays;
import java.util.Random;
import shuati2.chooseWork.jobCompator;
import shuti3.class3coffee;
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[] preAns = process(matrix,i,j);
res = Math.max(res, Math.max(preAns[0],preAns[1]));
}
}
return res;
}
public static int[] process(int[][]matrix,int i, int j) {
if(j == 0) {
return new int[]{matrix[i][j],-matrix[i][j]};
}
int[] preAns = process(matrix, i, j-1);
int preUnuse = preAns[0];
int preUse = preAns[1];
if(i-1>=0) {
preAns = process(matrix, i-1, j-1);
preUnuse = Math.max(preUnuse,preAns[0]);
preUse = Math.max(preUse, preAns[1]);
}
if(i+1 < matrix.length) {
preAns = process(matrix, i+1, j-1);
preUnuse = Math.max(preUnuse, preAns[0]);
preUse = Math.max(preUse, preAns[1]);
}
int no = -1;
int yes = -1;
if(preUnuse >=0) {
no = preUnuse + matrix[i][j];
yes = -matrix[i][j] + preUnuse;
}
if(preUse >= 0) {
yes = Math.max(yes,matrix[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 res = Integer.MIN_VALUE;
//创建三维dp数组
int[][][] dp = new int[matrix.length][matrix[0].length][2];
for(int i = 0; i < matrix.length;i++) {
dp[i][0][0] = matrix[i][0];
dp[i][0][1] = -matrix[i][0];
res = Math.max(res, 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 preUnsue = dp[i][j-1][0];
int preUse = dp[i][j-1][1];
if(i - 1 >=0) {
preUnsue = Math.max(preUnsue, dp[i-1][j-1][0]);
preUse = Math.max(preUse, dp[i-1][j-1][1]);
}
if(i+1 < matrix.length) {
preUnsue = Math.max(preUnsue, 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(preUnsue >=0) {
dp[i][j][0] = preUnsue + matrix[i][j];
dp[i][j][1] = -matrix[i][j] + preUnsue;
}
if(preUse >= 0) {
dp[i][j][1] = Math.max(dp[i][j][1], preUse + matrix[i][j]);
}
res = Math.max(res, Math.max(dp[i][j][0], dp[i][j][1]));
}
}
return res;
}
public static class Info{
private int no;
private int yes;
public Info(int no,int yes) {
this.no = no;
this.yes = yes;
}
}
public static int walk3(int[][] matrix) {
if(matrix == null || matrix.length == 0|| matrix[0].length==0) {
return 0;
}
int res = 0;
for(int i = 0; i < matrix.length; i++) {
for(int j = 0; j < matrix[0].length; j++) {
Info cur = InfoProcess(matrix,i,j);
res = Math.max(res, Math.max(cur.no, cur.yes));
}
}
return res;
}
public static Info InfoProcess(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);
}
Info cur = InfoProcess(matrix, i, j-1);
int preNo = -1;
int preYes = -1;
preNo = Math.max(preNo, cur.no);
preYes = Math.max(preYes, cur.yes);
if(i > 0) {
cur = InfoProcess(matrix, i-1, j-1);
preNo = Math.max(preNo, cur.no);
preYes = Math.max(preYes, cur.yes);
}
if(i < matrix.length-1) {
cur = InfoProcess(matrix, i+1, j-1);
preNo = Math.max(preNo, cur.no);
preYes = Math.max(preYes, cur.yes);
}
int no = preNo == -1 ? -1:Math.max(matrix[i][j]+preNo, -1);
//当此使用能力
int p2 = preNo == -1 ? -1 : Math.max(-1, -matrix[i][j] + preNo);
//之前使用能力
int p1 = preYes == -1 ? -1 : Math.max(-1, matrix[i][j] + preYes);
int yes = Math.max(-1,Math.max(p1, p2));
return new Info(no, yes);
}
public static int[][] generateRandomArray(int row,int col, int value){
int[][] arr = new int[row][col];
for(int i = 0; i < row; i++) {
for(int j = 0 ; j < col; 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 value = 2;
int times = 100000;
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, value);
int ans1 = walk1(matrix);
int ans2 = walk2(matrix);
int ans3 = walk3(matrix);
if(ans2 != ans3 || ans1 != ans2 || ans1 != ans3) {
for(int k = 0; k < matrix.length; k++) {
System.out.println(Arrays.toString(matrix[k]));
}
System.out.println("Oops ans1: "+ans1+" ans2: "+ans2 + " ans3: "+ans3);
break;
}
}
System.out.println("finish");
}
}