【递归到动态规划】:左右拿最大值问题

题目

在这里插入图片描述

思路

玩家都会有两个方法,就是先手拿牌和后手拿牌,先手拿牌的情况分两种拿左边的或者拿右边的,我们取二者中较大的,并且加上剩余牌后手拿的情况。然后分析后手拿的情况,后手拿一定是被动,而且对手已经选择了最好的情况,所以我们返回拿走牌剩余拿到较小的情况。最终的返回条件是只剩最后一张牌了。

代码

递归版

// 根据规则,返回获胜者的分数
public static int win1(int[] arr) {
	if (arr == null || arr.length == 0) {
		return 0;
	}
	int first = f1(arr, 0, arr.length - 1);
	int second = g1(arr, 0, arr.length - 1);
	return Math.max(first, second);
}

// arr[L..R],先手获得的最好分数返回
public static int f1(int[] arr, int L, int R) {
	if (L == R) {
		return arr[L];
	}
	int p1 = arr[L] + g1(arr, L + 1, R);
	int p2 = arr[R] + g1(arr, L, R - 1);
	return Math.max(p1, p2);
}

// // arr[L..R],后手获得的最好分数返回
public static int g1(int[] arr, int L, int R) {
	if (L == R) {
		return 0;
	}
	int p1 = f1(arr, L + 1, R); // 对手拿走了L位置的数
	int p2 = f1(arr, L, R - 1); // 对手拿走了R位置的数
	return Math.min(p1, p2);//对手留给你的肯定是最差的
}

动态规划版

public static int win3(int[] arr) {
	if (arr == null || arr.length == 0) {
		return 0;
	}
	int N = arr.length;
	int[][] f = new int[N][N];
	int[][] g = new int[N][N];
	for (int i = 0; i < N; i++) {
		f[i][i] = arr[i];//初始化对角线的值
	}
	for (int i = 1; i < N; i++) {
		int L = 0;
		int R = i;
		while (R < N) {
			f[L][R] = Math.max(arr[L] + g[L + 1][R], arr[R] + g[L][R - 1]);
			g[L][R] = Math.min(f[L + 1][R], f[L][R - 1]);
			L++;
			R++;
		}
	}
	return Math.max(f[0][N - 1], g[0][N - 1]);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值