- 题目
- 玩家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 小的值
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;
}
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);
int p2 = f2(arr, L, R - 1, fmap, gmap);
ans = Math.min(p1, p2);
}
gmap[L][R] = ans;
return ans;
}
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]);