栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

java算法题 之 递归到动态规划

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

java算法题 之 递归到动态规划

java算法题 之 递归到动态规划
    • 递归转动态规划
      • 机器人运动问题
        • 递归形式
        • 记忆搜索
        • 严格表结构
      • 飞棋盘
        • 递归实现
        • 严格表结构
      • 纸币组合
        • 暴力递归
        • 严格表结构
        • 枚举的斜率优化
      • 纸币组合最小个数问题
        • 递归实现
        • 严格表结构
      • 整数分裂
        • 暴力递归
        • 记忆化搜索
        • 基础动态规划
        • 斜率优化
      • 纸牌累计分数(序)(动归)
        • 递归实现
        • 严格表结构
      • bob活着
        • 递归实现
        • 严格表结构
      • 真假情况
        • 递归
        • 动规
      • 硬币结合动归
      • 能力蛇最大长度问题
        • 递归1
        • 递归2
        • 动归
    • 动归的空间压缩

递归转动态规划 机器人运动问题

题目:
参数N:1~N个位置
参数S:初始位置
参数E:终点位置
参数K:要走的步数
机器人在E位置要用K步走到S有几种选择

递归形式
class U {
    
    public static int fun(int N, int E, int S, int K) {
        return f(N, E, S, K);
    }
    
    private static int f(int N, int cur, int S, int k) {
        if (k == 0) return cur == S ? 1 : 0;
        if (cur == 1) return f(N, cur + 1, S, k - 1);
        if (cur == N)  return f(N, cur - 1, S, k - 1);
        return f(N, cur - 1, S, k - 1) + f(N, cur + 1, S, k - 1);
    }
}
记忆搜索
class U {
    private static int[][] arr;
    public static int fun(int N, int E, int S, int K) {
        arr=new int[K+1][N+1];
        for (int[] ints : arr) {
            Arrays.fill(ints, -1);
        }
        return f(N, E, S, K);
    }
    private static int f(int N, int cur, int S, int k) {
        if (arr[k][cur]!=-1) return arr[k][cur];
        if (k == 0) {
            arr[k][cur]=cur == S ? 1 : 0;
        }else if (cur == 1)
            arr[k][cur]=f(N, cur + 1, S, k - 1);
        else if (cur == N)  {
            arr[k][cur]=f(N, cur - 1, S, k - 1);
        }else {
            arr[k][cur]=f(N, cur - 1, S, k - 1) + f(N, cur + 1, S, k - 1);
        }
        return arr[k][cur];
    }
}
严格表结构

  • 确定变量以及变量范围
  • 标出目标位置,为返回结果
  • 递归结束条件(最终结果)
  • 确定依赖关系
  • 根据依赖按照合适填补的顺序填补
class U {
    
    public static int fun(int N, int E, int S, int K) {
        int[][] dp = new int[K + 1][N + 1];//dp[...][0]不用,这样好表示
        dp[0][S] = 1;//递归的结束条件就是我们的初始条件
        //根据递归依赖和初始条件的关系,推出填充表顺序
        for (int i = 1; i < K + 1; i++) {
            for (int cur = 1; cur < N + 1; cur++) {
                //三种依赖关系
                if (cur == 1) dp[i][cur] = dp[i - 1][cur + 1];
                else if (cur == N) dp[i][cur] = dp[i - 1][cur - 1];
                else dp[i][cur] = dp[i - 1][cur - 1] + dp[i - 1][cur + 1];
            }
        }
        //返回结果
        return dp[K][E];
    }
    public static void main(String[] args) {
        System.out.println(fun(4, 1, 3, 4));
    }
}
飞棋盘

问题:在像棋盘上给定起始位置问用K步从起始位置到(0,0)有几种选择

递归实现
class T{
	public static int process(int x, int y, int step) {
		if (x < 0 || x > 8 || y < 0 || y > 9) {
			return 0;
		}
		if (step == 0) {
			return (x == 0 && y == 0) ? 1 : 0;
		}
		return process(x - 1, y + 2, step - 1)
				+ process(x + 1, y + 2, step - 1)
				+ process(x + 2, y + 1, step - 1)
				+ process(x + 2, y - 1, step - 1)
				+ process(x + 1, y - 2, step - 1)
				+ process(x - 1, y - 2, step - 1)
				+ process(x - 2, y - 1, step - 1)
				+ process(x - 2, y + 1, step - 1);
	}
}
严格表结构
class U {
    public static int dp(int x, int y, int step) {
        if (x < 0 || y < 0 || x > 9 || y > 8) return 0;
        int[][][] dp = new int[10][9][step + 1];
        dp[0][0][0] = 1;//初始化条件
        for (int i = 1; i <= step; i++) {//层
            for (int row = 0; row <= 9; row++) {//行列前后无关
                for (int col = 0; col <= 8; col++) {
                    //依赖关系
                    dp[row][col][i]=getValue(dp, x - 1, y + 2, step - 1);
                    dp[row][col][i]=getValue(dp, x + 1, y + 2, step - 1);
                    dp[row][col][i]=getValue(dp, x + 2, y + 1, step - 1);
                    dp[row][col][i]=getValue(dp, x + 2, y - 1, step - 1);
                    dp[row][col][i]=getValue(dp, x + 1, y - 2, step - 1);
                    dp[row][col][i]=getValue(dp, x - 1, y - 2, step - 1);
                    dp[row][col][i]=getValue(dp, x - 2, y - 1, step - 1);
                    dp[row][col][i]=getValue(dp, x - 2, y + 1, step - 1);
                }
            }
        }
        return dp[x][y][step];
    }
    public static int getValue(int[][][] dp, int row, int col, int step) {
        if (row < 0 || row > 8 || col < 0 || col > 9) {
            return 0;
        }
        return dp[row][col][step];
    }
}
纸币组合

问题:给定数组arr,数据为面值种类,组成res的总值,每种面值可以任意使用,问共有多少种组合方式

暴力递归
class T {
    public static int process(int[] arr, int res) {
        return process(arr, 0, res);
    }
    private static int process(int[] arr, int index, int res) {
        //if (res == 0) return 1;两种判断方式不同动规初始有略微不同但是本质同
        //if (index == arr.length || res < 0) return 0;
        if (index == arr.length ) return res==0?1:0;
        
        int ways = 0;
        for (int num = 0; arr[index] * num <= res; num++) {
            ways += process(arr, index + 1, res - arr[index] * num);
        }
        return ways;
    }
}
严格表结构
class T {
    public static int process(int[] arr, int res) {
        int[][] dp = new int[arr.length + 1][res + 1];
//        for (int i = 0; i < arr.length; i++) {
//            dp[i][0]=1;
//        }跟递归结束条件有关
        dp[arr.length][0] = 1;
        for (int index = arr.length - 1; index >= 0; index--) {
            for (int r = 0; r <= res; r++) {
                int ways = 0;
                for (int num = 0; arr[index] * num <= r; num++) {//这里的范围为 <=r   不是res
                    ways += dp[index + 1][r - arr[index] * num];
                }
                dp[index][r] = ways;
            }
        }
        return dp[0][res];
    }
}
枚举的斜率优化
class T {
    public static int process(int[] arr, int res) {
        int[][] dp = new int[arr.length + 1][res + 1];
        dp[arr.length][0] = 1;
        for (int index = arr.length - 1; index >= 0; index--) {
            for (int r = 0; r <= res; r++) {
                //存在枚举递进关系,在严格表结构时相当于有重复计算,这里通过观察有某种递进关系(不需要直到本质含义,就是结构问题)
                dp[index][r]=dp[index+1][r];
                if (r-arr[index]>=0){
                    dp[index][r]+=dp[index][r-arr[index]];
                }
            }
        }
        return dp[0][res];
    }
}
纸币组合最小个数问题

题目:给定数组arr,里面的每个值表示一种面值,可随意使用,问组成aim所需要的最小张数,并返回

递归实现
	public static int minCoins1(int[] arr, int aim) {
		if (arr == null || arr.length == 0 || aim < 0) {
			return -1;
		}
		return process(arr, 0, aim);
	}

	// 当前考虑的面值是arr[i],还剩rest的钱需要找零
	// 如果返回-1说明自由使用arr[i..N-1]面值的情况下,无论如何也无法找零rest
	// 如果返回不是-1,代表自由使用arr[i..N-1]面值的情况下,找零rest需要的最少张数
	public static int process(int[] arr, int i, int rest) {
		// base case:
		// 已经没有面值能够考虑了
		// 如果此时剩余的钱为0,返回0张
		// 如果此时剩余的钱不是0,返回-1
		if (i == arr.length) {
			return rest == 0 ? 0 : -1;
		}
		// 最少张数,初始时为-1,因为还没找到有效解
		int res = -1;
		// 依次尝试使用当前面值(arr[i])0张、1张、k张,但不能超过rest
		for (int k = 0; k * arr[i] <= rest; k++) {
			// 使用了k张arr[i],剩下的钱为rest - k * arr[i]
			// 交给剩下的面值去搞定(arr[i+1..N-1])
			int next = process(arr, i + 1, rest - k * arr[i]);
			if (next != -1) { // 说明这个后续过程有效
				res = res == -1 ? next + k : Math.min(res, next + k);
			}
		}
		return res;
	}
严格表结构
	public static int minCoins2(int[] arr, int aim) {
		if (arr == null || arr.length == 0 || aim < 0) {
			return -1;
		}
		int N = arr.length;
		int[][] dp = new int[N + 1][aim + 1];
		// 设置最后一排的值,除了dp[N][0]为0之外,其他都是-1
		for (int col = 1; col <= aim; col++) {
			dp[N][col] = -1;
		}
		for (int i = N - 1; i >= 0; i--) { // 从底往上计算每一行
			for (int rest = 0; rest <= aim; rest++) { // 每一行都从左往右
				dp[i][rest] = -1; // 初始时先设置dp[i][rest]的值无效
				if (dp[i + 1][rest] != -1) { // 下面的值如果有效
					dp[i][rest] = dp[i + 1][rest]; // dp[i][rest]的值先设置成下面的值
				}
				// 左边的位置不越界并且有效
				if (rest - arr[i] >= 0 && dp[i][rest - arr[i]] != -1) {
					if (dp[i][rest] == -1) { // 如果之前下面的值无效
						dp[i][rest] = dp[i][rest - arr[i]] + 1;
					} else { // 说明下面和左边的值都有效,取最小的
						dp[i][rest] = Math.min(dp[i][rest],
								dp[i][rest - arr[i]] + 1);
					}
				}
			}
		}
		return dp[0][aim];
	}
整数分裂

暴力递归
public class Main {
	public static int ways1(int n) {
		if (n < 1) {
			return 0;
		}
		return process(1, n);
	}

	public static int process(int pre, int rest) {
		if (rest == 0) {
			return 1;
		}
		if (pre > rest) {
			return 0;
		}
		int ways = 0;
		for (int i = pre; i <= rest; i++) {
			ways += process(i, rest - i);
		}
		return ways;
	}
}
记忆化搜索
public class Main {
	public static int ways1(int n) {
		if (n < 1) {
			return 0;
		}
		int[][] arr = new int[n + 1][n + 1];
		for (int[] is : arr) {
			Arrays.fill(is, -1);
		}
		return process(1, n, arr);
	}

	public static int process(int pre, int rest, int[][] dp) {
		if (dp[pre][rest] != -1) {
			return dp[pre][rest];
		}
		if (rest == 0) {
			dp[pre][rest] = 1;
			return 1;
		}
		if (pre > rest) {
			dp[pre][rest] = 0;
			return 0;
		}
		int ways = 0;
		for (int i = pre; i <= rest; i++) {
			ways += process(i, rest - i, dp);
		}
		dp[pre][rest] = ways;
		return ways;
	}
}
基础动态规划
public class Main {
	public static int ways2(int n) {
		if (n < 1) {
			return 0;
		}
		int[][] dp = new int[n + 1][n + 1];
		for (int pre = 1; pre < dp.length; pre++) {
			dp[pre][0] = 1;
		}
		for (int pre = n; pre > 0; pre--) {
			for (int rest = pre; rest <= n; rest++) {
				for (int i = pre; i <= rest; i++) {
					dp[pre][rest] += dp[i][rest - i];
				}
			}
		}
		return dp[1][n];
	}
}
斜率优化
  • 枚举行为推导
public class Main {
	public static int ways3(int n) {
		if (n < 1) {
			return 0;
		}
		int[][] dp = new int[n + 1][n + 1];
		for (int pre = 1; pre < dp.length; pre++) {
			dp[pre][0] = 1;
		}
		for (int pre = 1; pre < dp.length; pre++) {
			dp[pre][pre] = 1;
		}
		for (int pre = n - 1; pre > 0; pre--) {
			for (int rest = pre + 1; rest <= n; rest++) {
				dp[pre][rest] = dp[pre + 1][rest] + dp[pre][rest - pre];
			}
		}
		return dp[1][n];
	}
}
纸牌累计分数(序)(动归) 递归实现
    public static int win(int[] arr) {
        return Math.max(f(arr, 0, arr.length - 1), e(arr, 0, arr.length - 1));
    }
    public static int f(int[] arr, int l, int r) {
        if (l == r) return arr[l];
        return Math.max(arr[l] + e(arr, l + 1, r), arr[r] + e(arr, l, r - 1));
    }
    public static int e(int[] arr, int l, int r) {
        if (l == r) return 0;
        return Math.min(f(arr, l + 1, r), f(arr, l, r - 1));
    }

严格表结构

class U {

	//斜线填充
    public static int dp(int[] arr) {
        if (arr == null || arr.length == 0) return 0;
        int[][] f = new int[arr.length][arr.length];
        int[][] s = new int[arr.length][arr.length];
        for (int i = 0; i < arr.length; i++) {
            f[i][i] = arr[i];//递归的结束条件就是我们的初始条件
        }
        int row = 0;
        for (int col = 1; col < arr.length; col++) {
            for (int i = row, j = col; i < arr.length && j < arr.length; i++, j++) {
            	//依赖关系
                f[i][j] = Math.max(arr[i] + s[i + 1][j], arr[j] + s[i][j - 1]);
                s[i][j] = Math.min(f[i + 1][j], f[i][j - 1]);
            }
        }
        return Math.max(f[0][arr.length - 1], s[0][arr.length - 1]);
    }
    //竖向填充
    public static int win2(int[] arr) {
        if (arr == null || arr.length == 0) {
            return 0;
        }
        int[][] f = new int[arr.length][arr.length];
        int[][] s = new int[arr.length][arr.length];
        for (int i = 0; i < arr.length; i++) {
            f[i][i] = arr[i];
        }
        for (int j = 0; j < arr.length; j++) {
            for (int i = j - 1; i >= 0; i--) {
                f[i][j] = Math.max(arr[i] + s[i + 1][j], arr[j] + s[i][j - 1]);
                s[i][j] = Math.min(f[i + 1][j], f[i][j - 1]);
            }
        }
        return Math.max(f[0][arr.length - 1], s[0][arr.length - 1]);
    }
}
bob活着

题目:给定范围横向N,纵向M,从(i,j)开始走K步(只能上下左右走,且概率相同)没有超过给定范围那么就是活着,如果在过程中超过了范围则死了,返回活着的概率。

递归实现
class U {
    
    public static String bob1(int N, int M, int i, int j, int K) {
        long all = (long) Math.pow(4, K); // 总共有all中情况
        long live = process(N, M, i, j, K); //存活情况个数
        long gcd = gcd(all, live);//求最大公约数
        return (live / gcd) + " / " + (all / gcd);
    }

    public static long process(int N, int M, int row, int col, int rest) {
        if (row < 0 || row >= N || col < 0 || col >= M) {
            return 0;
        }
        if (rest == 0) {
            return 1;
        }
        long live = process(N, M, row - 1, col, rest - 1);
        live += process(N, M, row + 1, col, rest - 1);
        live += process(N, M, row, col - 1, rest - 1);
        live += process(N, M, row, col + 1, rest - 1);
        return live;
    }

	//求最大公约数
    public static long gcd(long m, long n) {
        return n == 0 ? m : gcd(n, m % n);
    }
}
严格表结构
class U {
    public static long gcd(long m, long n) {
        return n == 0 ? m : gcd(n, m % n);
    }

    public static String bob2(int N, int M, int i, int j, int K) {
        int[][][] dp = new int[N + 2][M + 2][K + 1];
        for (int row = 1; row <= N; row++) {//初始化数据
            for (int col = 1; col <= M; col++) {
                dp[row][col][0] = 1;
            }
        }
        for (int rest = 1; rest <= K; rest++) {
            for (int row = 1; row <= N; row++) {
                for (int col = 1; col <= M; col++) {
                	//递归依赖
                    dp[row][col][rest] = dp[row - 1][col][rest - 1];
                    dp[row][col][rest] += dp[row + 1][col][rest - 1];
                    dp[row][col][rest] += dp[row][col - 1][rest - 1];
                    dp[row][col][rest] += dp[row][col + 1][rest - 1];
                }
            }
        }
        long all = (long) Math.pow(4, K);
        long live = dp[i + 1][j + 1][K];
        long gcd = gcd(all, live);
        return (live / gcd) + "/" + (all / gcd);
    }
}
真假情况

递归
class Test {
    private static boolean isValid(char[] exp) {
        if ((exp.length & 1) == 0) {
            return false;
        }
        for (int i = 0; i < exp.length; i = i + 2) {
            if ((exp[i] != '1') && (exp[i] != '0')) {
                return false;
            }
        }
        for (int i = 1; i < exp.length; i = i + 2) {
            if ((exp[i] != '&') && (exp[i] != '|') && (exp[i] != '^')) {
                return false;
            }
        }
        return true;
    }

    public static int num1(String express, boolean desired) {
        if (express == null || express.equals("")) {
            return 0;
        }
        char[] exp = express.toCharArray();
        if (!isValid(exp)) {
            return 0;
        }
        return p(exp, desired, 0, exp.length - 1);
    }

    private static int p(char[] exp, boolean desired, int L, int R) {
        if (L == R) {
            if (exp[L] == '1') {
                return desired ? 1 : 0;
            } else {
                return desired ? 0 : 1;
            }
        }
        int res = 0;
        if (desired) {
            for (int i = L + 1; i < R; i += 2) {
                switch (exp[i]) {
                    case '&':
                        res += p(exp, true, L, i - 1) * p(exp, true, i + 1, R);
                        break;
                    case '|':
                        res += p(exp, true, L, i - 1) * p(exp, false, i + 1, R);
                        res += p(exp, false, L, i - 1) * p(exp, true, i + 1, R);
                        res += p(exp, true, L, i - 1) * p(exp, true, i + 1, R);
                        break;
                    case '^':
                        res += p(exp, true, L, i - 1) * p(exp, false, i + 1, R);
                        res += p(exp, false, L, i - 1) * p(exp, true, i + 1, R);
                        break;
                }
            }
        } else {
            for (int i = L + 1; i < R; i += 2) {
                switch (exp[i]) {
                    case '&':
                        res += p(exp, false, L, i - 1) * p(exp, true, i + 1, R);
                        res += p(exp, true, L, i - 1) * p(exp, false, i + 1, R);
                        res += p(exp, false, L, i - 1) * p(exp, false, i + 1, R);
                        break;
                    case '|':
                        res += p(exp, false, L, i - 1) * p(exp, false, i + 1, R);
                        break;
                    case '^':
                        res += p(exp, true, L, i - 1) * p(exp, true, i + 1, R);
                        res += p(exp, false, L, i - 1) * p(exp, false, i + 1, R);
                        break;
                }
            }
        }
        return res;
    }
}
动规
class Test {
    public static int num2(String express, boolean desired) {
        if (express == null || express.equals("")) {
            return 0;
        }
        char[] exp = express.toCharArray();
        if (!isValid(exp)) {
            return 0;
        }
        int[][] t = new int[exp.length][exp.length];
        int[][] f = new int[exp.length][exp.length];
        t[0][0] = exp[0] == '0' ? 0 : 1;
        f[0][0] = exp[0] == '1' ? 0 : 1;
        for (int i = 2; i < exp.length; i += 2) {
            t[i][i] = exp[i] == '0' ? 0 : 1;
            f[i][i] = exp[i] == '1' ? 0 : 1;
            for (int j = i - 2; j >= 0; j -= 2) {
                for (int k = j; k < i; k += 2) {
                    if (exp[k + 1] == '&') {
                        t[j][i] += t[j][k] * t[k + 2][i];
                        f[j][i] += (f[j][k] + t[j][k]) * f[k + 2][i] + f[j][k] * t[k + 2][i];
                    } else if (exp[k + 1] == '|') {
                        t[j][i] += (f[j][k] + t[j][k]) * t[k + 2][i] + t[j][k] * f[k + 2][i];
                        f[j][i] += f[j][k] * f[k + 2][i];
                    } else {
                        t[j][i] += f[j][k] * t[k + 2][i] + t[j][k] * f[k + 2][i];
                        f[j][i] += f[j][k] * f[k + 2][i] + t[j][k] * t[k + 2][i];
                    }
                }
            }
        }
        return desired ? t[0][t.length - 1] : f[0][f.length - 1];
    }
}
硬币结合动归

class MoneyWays {
	//主调函数
    public static int moneyWays(int[] arbitrary, int[] onlyone, int money) {
        if (money < 0) {
            return 0;
        }
        if ((arbitrary == null || arbitrary.length == 0)
                && (onlyone == null || onlyone.length == 0)) {
            return money == 0 ? 1 : 0;
        }
        int[][] dparb = getDpArb(arbitrary, money);
        int[][] dpone = getDpOne(onlyone, money);
        if (dparb == null) {
            return dpone[dpone.length - 1][money];
        }
        if (dpone == null) {
            return dparb[dparb.length - 1][money];
        }
        int res = 0;
        for (int i = 0; i <= money; i++) {
            res += dparb[dparb.length - 1][i]
                    * dpone[dpone.length - 1][money - i];
        }
        return res;
    }
	//多个硬币的方法
    private static int[][] getDpArb(int[] arr, int money) {
        if (arr == null || arr.length == 0) {
            return null;
        }
        int[][] dp = new int[arr.length][money + 1];
        for (int i = 0; i < arr.length; i++) {
            dp[i][0] = 1;
        }
        for (int j = 1; arr[0] * j <= money; j++) {
            dp[0][arr[0] * j] = 1;
        }
        for (int i = 1; i < arr.length; i++) {
            for (int j = 1; j <= money; j++) {
                dp[i][j] = dp[i - 1][j];
                dp[i][j] += j - arr[i] >= 0 ? dp[i][j - arr[i]] : 0;
            }
        }
        return dp;
    }
	//一个硬币的情况
    private static int[][] getDpOne(int[] arr, int money) {
        if (arr == null || arr.length == 0) {
            return null;
        }
        int[][] dp = new int[arr.length][money + 1];
        for (int i = 0; i < arr.length; i++) {
            dp[i][0] = 1;
        }
        if (arr[0] <= money) {
            dp[0][arr[0]] = 1;
        }
        for (int i = 1; i < arr.length; i++) {
            for (int j = 1; j <= money; j++) {
                dp[i][j] = dp[i - 1][j];
                dp[i][j] += j - arr[i] >= 0 ? dp[i - 1][j - arr[i]] : 0;
            }
        }
        return dp;
    }
}
能力蛇最大长度问题

递归1
public class Main {
	public static int fun(int[][] m) {
		if (m == null || m.length == 0 || m[0].length == 0) {
			return 0;
		}
		int res = Integer.MIN_VALUE;
		for (int i = 0; i < m.length; i++) {
			int ans = fun(m, i, 0, 0, false);
			res = Math.max(res, ans);
		}
		return res;
	}

	private static int fun(int[][] m, int i, int j, Integer num, boolean falg) {

		if (j == m[0].length - 1) {
			return falg ? Math.max(num, num+m[i][j]) : Math.max(num + m[i][j], num - m[i][j]);
		}
		int no = num;
		int yes = num;
		//只有一行
		if (m.length==1) {
			if (!falg&& m[i][j] < 0) {
				no=fun(m,i,j+1,num-m[i][j],!falg);
			}
			yes=fun(m, i, j+1, num+m[i][j], falg);
			return Math.max(no, yes);
		}
		if (i == 0) {
			if (!falg && m[i][j] < 0) {
				no = Math.max(fun(m, i, j + 1, num - m[i][j], !falg), fun(m, i + 1, j + 1, num - m[i][j], !falg));
			}
			if (num + m[i][j] > 0) {
				yes = Math.max(fun(m, i, j + 1, num + m[i][j], falg), fun(m, i + 1, j + 1, num + m[i][j], falg));
			}
			return Math.max(no, yes);
		} else if (i == m.length - 1) {
			if (!falg && m[i][j] < 0) {
				no = Math.max(fun(m, i-1, j +1 , num - m[i][j], !falg), fun(m, i , j +1, num - m[i][j], !falg));
			}
			if (num + m[i][j] > 0) {
				yes = Math.max(fun(m, i-1, j + 1, num + m[i][j], falg), fun(m, i , j + 1, num + m[i][j], falg));
			}
			return Math.max(no, yes);
		} else {
			if (!falg && m[i][j] < 0) {
				no = Math.max(fun(m, i, j + 1, num - m[i][j], !falg),
						Math.max(fun(m, i + 1, j + 1, num - m[i][j], !falg), fun(m, i-1, j + 1, num - m[i][j], !falg)));
			}
			if (num + m[i][j] > 0) {
				yes = Math.max(fun(m, i + 1, j + 1, num + m[i][j], falg),
						Math.max(fun(m, i, j + 1, num, falg), fun(m, i - 1, j + 1, num + m[i][j], falg)));
			}
			return Math.max(no, yes);
		}
	}
}
递归2
class Main {
	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++) {
			int[] ans = process(matrix, i, 0);
			res = Math.max(res, Math.max(ans[0], ans[1]));
		}
		return res;
	}

	public static int fun(int[][] m) {
		int res = Integer.MIN_VALUE;
		for (int i = 0; i < m.length; i++) {
			int ans = fun(m, i, 0, 0, false);
			res = Math.max(res, ans);
		}
		return res;
	}

	// 从(i,j)出发一直走到最右侧的旅程中
	// 0) 在没有使用过能力的情况下,返回路径最大和
	// 1) 在使用过能力的情况下,返回路径最大和
	public static int[] process(int[][] m, int i, int j) {
		if (j == m[0].length - 1) {
			return new int[] { m[i][j], -m[i][j] };
		}
		int[] restAns = process(m, i, j + 1);
		int restUnuse = restAns[0];
		int restUse = restAns[1];
		if (i - 1 >= 0) {
			restAns = process(m, i - 1, j + 1);
			restUnuse = Math.max(restUnuse, restAns[0]);
			restUse = Math.max(restUse, restAns[1]);
		}
		if (i + 1 < m.length) {
			restAns = process(m, i + 1, j + 1);
			restUnuse = Math.max(restUnuse, restAns[0]);
			restUse = Math.max(restUse, restAns[1]);
		}
		int no = m[i][j] + restUnuse;
		int yes = Math.max(m[i][j] + restUse, -m[i][j] + restUnuse);
		return new int[] { no, yes };
	}
}
动归
class Main {
	public static int walk2(int[][] matrix) {
		if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
			return 0;
		}
		int[][][] dp = new int[matrix.length][matrix[0].length][2];
		for (int i = 0; i < dp.length; i++) {
			dp[i][matrix[0].length - 1][0] = matrix[i][matrix[0].length - 1];
			dp[i][matrix[0].length - 1][1] = -matrix[i][matrix[0].length - 1];
		}
		for (int j = matrix[0].length - 2; j >= 0; j--) {
			for (int i = 0; i < matrix.length; i++) {
				int restUnuse = dp[i][j + 1][0];
				int restUse = dp[i][j + 1][1];
				if (i - 1 >= 0) {
					restUnuse = Math.max(restUnuse, dp[i - 1][j + 1][0]);
					restUse = Math.max(restUse, dp[i - 1][j + 1][1]);
				}
				if (i + 1 < matrix.length) {
					restUnuse = Math.max(restUnuse, dp[i + 1][j + 1][0]);
					restUse = Math.max(restUse, dp[i + 1][j + 1][0]);
				}
				dp[i][j][0] = matrix[i][j] + restUnuse;
				dp[i][j][1] = Math.max(matrix[i][j] + restUse, -matrix[i][j] + restUnuse);
			}
		}

		int res = Integer.MIN_VALUE;
		for (int i = 0; i < matrix.length; i++) {
			res = Math.max(res, Math.max(dp[i][0][0], dp[i][0][1]));
		}
		return res;
	}
}
动归的空间压缩



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/343697.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号