class Solution {
Integer[][] cache; // integer 后面才可以判空,应用数据类型默认值为null,基本数据类型默认值就是基本数据类型的默认值
public int stoneGameII(int[] piles) {
cache = new Integer[piles.length][piles.length * 2];
int totalStones = 0;
for(int stone : piles) {
totalStones += stone;
}
//(Alice's Stone + Bob's Stone) = totalStones
//(Alice's Stone - Bob's Stone) = Alice's score
// 2 * Alice's Stone = totalStones + Alice's score
//Alice's Stone = (totalStones + Alice's score) / 2
return (totalStones + getAliceScore(piles, 0, 1)) / 2;
}
private int getAliceScore(int[] piles, int index, int M) {
if(index == piles.length) {
return 0;
}
if(cache[index][M] != null) {
return cache[index][M];
}
int maxScore = Integer.MIN_VALUE;
int stone = 0;
for(int x = 0; x < 2 * M; x++) {
int i = index + x;
if(i >= piles.length) {
continue;
}
stone += piles[i];
int score = stone - getAliceScore(piles, i + 1, Math.max(x + 1, M));
maxScore = Math.max(maxScore, score);
}
return cache[index][M] = maxScore;
}
}
877. Stone Game
class Solution {
public boolean stoneGame(int[] piles) {
int n = piles.length;
// dp[i][j] 表示在石头堆的第 i 到第 j 堆中,当前玩家与对手的得分差
int dp[][] = new int[n][n];
for(int i = 0; i < n; i++) {
// 只有一堆时,对角线上的元素
dp[i][i] = piles[i];
}
// 外层循环 l 表示石头堆的数量范围,从2开始,即从两堆石头开始考虑
for(int l = 2; l <= n; l++) {
// 内层循环 i 表示石头堆的起始位置
for(int i = 0; i + l - 1 < n; i++) {
int j = i + l - 1; //计算当前范围的结束位置
int a = piles[i] - dp[i + 1][j]; // 假设从i堆开始
int b = piles[j] - dp[i][j - 1]; // 假设从j堆开始
dp[i][j] = Integer.max(a, b);
}
}
return dp[0][n - 1] > 0;
}
}