两玩家从左右两端取纸牌,求获胜者分数

  • 题目
    • 玩家A和玩家B依次拿走每张纸牌,
      规定玩家A先拿,玩家B后拿,
      但是每个玩家每次只能拿走最左或最右的纸牌,
      玩家A和玩家B都绝顶聪明。请返回最后获胜者的分数。
  • 思路:两个函数,f()先拿时最大值,s()后拿时最大值
  • 限制:只有一张时f能拿,s不能拿
  • f函数两种拿法
    • int p1 = arr[L] + s1(arr, L + 1, R);
      int p2 = arr[R] + s1(arr, L, R - 1);
    • return 大的值
  • s函数
    • int p1 = f1(arr, L + 1, R); // 对手拿走了L位置的数
      int p2 = f1(arr, L, R - 1); // 对手拿走了R位置的数
    • 因为先手有选择权,所以return 小的值
// arr[L..R],先手获得的最好分数返回
	public static int f2(int[] arr, int L, int R, int[][] fmap, int[][] gmap) {
		if (fmap[L][R] != -1) {
			return fmap[L][R];
		}
		int ans = 0;
		if (L == R) {
			ans = arr[L];
		} else {
			int p1 = arr[L] + g2(arr, L + 1, R, fmap, gmap);
			int p2 = arr[R] + g2(arr, L, R - 1, fmap, gmap);
			ans = Math.max(p1, p2);
		}
		fmap[L][R] = ans;
		return ans;
	}

	// // arr[L..R],后手获得的最好分数返回
	public static int g2(int[] arr, int L, int R, int[][] fmap, int[][] gmap) {
		if (gmap[L][R] != -1) {
			return gmap[L][R];
		}
		int ans = 0;
		if (L != R) {
			int p1 = f2(arr, L + 1, R, fmap, gmap); // 对手拿走了L位置的数
			int p2 = f2(arr, L, R - 1, fmap, gmap); // 对手拿走了R位置的数
			ans = Math.min(p1, p2);
		}
		gmap[L][R] = ans;
		return ans;
	}


//方法2
//- dp:两个独立函数用两张表,每个函数只有LR,用二维表示。fdp[L][R]表示L~R范围上先手最大分数  
//- 普遍依赖:
fmap[L][R] = Math.max(arr[L] + gmap[L + 1][R], arr[R] + gmap[L][R - 1]);
gmap[L][R] = Math.min(fmap[L + 1][R], fmap[L][R - 1]);  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值