JAVA实现贪吃蛇算法

问题:给定一个矩阵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");
	}
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值