publicintdp(Map<Integer, Integer> memo, int[] piles, int[] prefixSum, int i, int m) { if (i == piles.length) { return0; } intkey= i * 201 + m; if (!memo.containsKey(key)) { intmaxVal= Integer.MIN_VALUE; for (intx=1; x <= 2 * m; x++) { if (i + x > piles.length) { break; } maxVal = Math.max(maxVal, prefixSum[i + x] - prefixSum[i] - dp(memo, piles, prefixSum, i + x, Math.max(m, x))); } memo.put(key, maxVal); } return memo.get(key); } }
publicintDP(IDictionary<int, int> memo, int[] piles, int[] prefixSum, int i, int m) { if (i == piles.Length) { return0; } int key = i * 201 + m; if (!memo.ContainsKey(key)) { int maxVal = int.MinValue; for (int x = 1; x <= 2 * m; x++) { if (i + x > piles.Length) { break; } maxVal = Math.Max(maxVal, prefixSum[i + x] - prefixSum[i] - DP(memo, piles, prefixSum, i + x, Math.Max(m, x))); } memo.Add(key, maxVal); } return memo[key]; } }
classSolution { public: intstoneGameII(vector<int>& piles){ int n = piles.size(); vector<vector<int>> dp(n + 1, vector<int>(n + 1, INT_MIN)); for (int i = n; i >= 0; i--) { for (int m = 1; m <= n; m++) { if (i == n) { dp[i][m] = 0; } else { int sum = 0; for (int x = 1; x <= 2 * m; x++) { if (i + x > n) { break; } sum += piles[i + x - 1]; dp[i][m] = max(dp[i][m], sum - dp[i + x][min(n, max(m, x))]); } } } } return (dp[0][1] + accumulate(piles.begin(), piles.end(), 0)) / 2; } };
staticinlineintmax(int a, int b) { return a > b ? a : b; }
staticinlineintmin(int a, int b) { return a < b ? a : b; }
intstoneGameII(int* piles, int pilesSize) { int n = pilesSize; int dp[n + 1][n + 1]; for (int i = 0; i <= n; i++) { for (int j = 0; j <= n; j++) { dp[i][j] = INT_MIN; } } for (int i = n; i >= 0; i--) { for (int m = 1; m <= n; m++) { if (i == n) { dp[i][m] = 0; } else { int sum = 0; for (int x = 1; x <= 2 * m; x++) { if (i + x > n) { break; } sum += piles[i + x - 1]; dp[i][m] = max(dp[i][m], sum - dp[i + x][min(n, max(m, x))]); } } } } int sum = 0; for (int i = 0; i < n; i++) { sum += piles[i]; } return (dp[0][1] + sum) / 2; }
constdp = (memo, piles, prefixSum, i, m) => { if (i === piles.length) { return0; } const key = i * 201 + m; if (!memo.has(key)) { let maxVal = -Number.MAX_VALUE; for (let x = 1; x <= 2 * m; x++) { if (i + x > piles.length) { break; } maxVal = Math.max(maxVal, prefixSum[i + x] - prefixSum[i] - dp(memo, piles, prefixSum, i + x, Math.max(m, x))); } memo.set(key, maxVal); } return memo.get(key); };
funcstoneGameII(piles []int)int { prefixSum := make([]int, len(piles)+1) for i, v := range piles { prefixSum[i+1] = prefixSum[i] + v } type pair struct{ i, m int } dp := map[pair]int{} var f func(int, int)int f = func(i int, m int)int { if i == len(piles) { return0 } if v, ok := dp[pair{i, m}]; ok { return v } maxVal := math.MinInt for x := 1; x <= 2*m; x++ { if i+x > len(piles) { break } maxVal = max(maxVal, prefixSum[i+x]-prefixSum[i]-f(i+x, max(m, x))) } dp[pair{i, m}] = maxVal return maxVal } return (prefixSum[len(piles)] + f(0, 1)) / 2 }
funcmax(a, b int)int { if b > a { return b } return a }
复杂度分析
时间复杂度:O(n^3),其中 n 是数组 piles 的长度。记忆化搜索的状态数为 O(n^2),每个状态消耗 O(n) 求解。