[leetcode] problem 1140 – stone game ii

Alex and Lee continue their games with piles of stones. There are a number of piles arranged in a row, and each pile has a positive integer number of stones piles[i]. The objective of the game is to end with the most stones.

Alex and Lee take turns, with Alex starting first. Initially, M = 1.

On each player’s turn, that player can take all the stones in the first X remaining piles, where 1 <= X <= 2M. Then, we set M = max(M, X).

The game continues until all the stones have been taken.

Assuming Alex and Lee play optimally, return the maximum number of stones Alex can get.

Example

Input: piles = [2,7,9,4,4]

Output: 10

Explanation: If Alex takes one pile at the beginning, Lee takes two piles, then Alex takes 2 piles again. Alex can get 2 + 4 + 4 = 10 piles in total. If Alex takes two piles at the beginning, then Lee can take all three piles left. In this case, Alex get 2 + 7 = 9 piles in total. So we return 10 since it’s larger.

Constraints

  • 1 <= piles.length <= 100
  • 1 <= piles[i] <= 10 ^ 4

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
private int[] sum;
private int[][] memo;

public int (int[] piles) {
int n = piles.length;
sum = new int[n];
memo = new int[n][n];

for (int i = 0; i < n; i++)
sum[i] = (i == 0 ? 0 : sum[i - 1]) + piles[i];

return (sum[n - 1] + helper(piles, n, 0, 1)) / 2;
}

private int helper(int[] piles, int n, int s, int M) {
if (s >= n)
return 0;

if (memo[s][M] != 0)
return memo[s][M];

int max = Integer.MIN_VALUE;

for (int x = 1; x <= 2 * M; x++) {
if (s + x > n)
break;

max = Math.max(max, sum[s + x - 1] - (s == 0 ? 0 : sum[s - 1])
- helper(piles, n, s + x, Math.max(x, M)));
}

memo[s][M] = max;
return max;
}