From 99f80d75f17e2f44f71ba8a45cc4475c16ffe3b2 Mon Sep 17 00:00:00 2001 From: yanglbme Date: Wed, 25 Dec 2024 09:01:22 +0800 Subject: [PATCH] feat: add solutions to lc problem: No.1563 No.1563.Stone Game V --- .../1500-1599/1563.Stone Game V/README.md | 179 ++++++++++------- .../1500-1599/1563.Stone Game V/README_EN.md | 184 ++++++++++++------ .../1500-1599/1563.Stone Game V/Solution.cpp | 35 ++-- .../1500-1599/1563.Stone Game V/Solution.go | 31 +-- .../1500-1599/1563.Stone Game V/Solution.java | 33 ++-- .../1500-1599/1563.Stone Game V/Solution.py | 29 +-- .../1500-1599/1563.Stone Game V/Solution.ts | 38 ++++ 7 files changed, 344 insertions(+), 185 deletions(-) create mode 100644 solution/1500-1599/1563.Stone Game V/Solution.ts diff --git a/solution/1500-1599/1563.Stone Game V/README.md b/solution/1500-1599/1563.Stone Game V/README.md index e3c6f844a667b..7f64cdd5f56c9 100644 --- a/solution/1500-1599/1563.Stone Game V/README.md +++ b/solution/1500-1599/1563.Stone Game V/README.md @@ -69,48 +69,53 @@ tags: ### 方法一:记忆化搜索 + 剪枝 -我们先预处理出前缀和数组 $s$,其中 $s[i]$ 表示数组 $stoneValue$ 前 $i$ 个元素的和。 +我们先预处理出前缀和数组 $\textit{s}$,其中 $\textit{s}[i]$ 表示数组 $\textit{stoneValue}$ 前 $i$ 个元素的和。 -接下来,我们设计一个函数 $dfs(i, j)$,表示数组 $stoneValue$ 中下标范围 $[i, j]$ 内的石子,Alice 能够获得的最大分数。那么答案就是 $dfs(0, n - 1)$。 +接下来,我们设计一个函数 $\textit{dfs}(i, j)$,表示数组 $\textit{stoneValue}$ 中下标范围 $[i, j]$ 内的石子,Alice 能够获得的最大分数。那么答案就是 $\textit{dfs}(0, n - 1)$。 -函数 $dfs(i, j)$ 的计算过程如下: +函数 $\textit{dfs}(i, j)$ 的计算过程如下: -- 如果 $i = j$,说明只剩下一块石子,Alice 无法进行分割,因此返回 $0$。 -- 否则,我们枚举分割点 $k$,即 $i \leq k \lt j$,将数组 $stoneValue$ 中下标范围 $[i, j]$ 内的石子分割为 $[i, k]$ 和 $[k + 1, j]$ 两部分,计算出 $a$ 和 $b$,分别表示两部分的石子总和。然后我们分别计算 $dfs(i, k)$ 和 $dfs(k + 1, j)$,并更新答案。 +- 如果 $i \geq j$,说明只剩下一块石子,Alice 无法进行分割,因此返回 $0$。 +- 否则,我们枚举分割点 $k$,即 $i \leq k < j$,将数组 $\textit{stoneValue}$ 中下标范围 $[i, j]$ 内的石子分割为 $[i, k]$ 和 $[k + 1, j]$ 两部分,计算出 $a$ 和 $b$,分别表示两部分的石子总和。然后我们分别计算 $\textit{dfs}(i, k)$ 和 $\textit{dfs}(k + 1, j)$,并更新答案。 -注意,如果满足 $a \lt b$ 并且 $ans \geq a \times 2$,那么这一次枚举可以跳过;如果满足 $a \gt b$ 并且 $ans \geq b \times 2$,那么后续的枚举都可以跳过,直接退出循环。 +注意,如果满足 $a < b$ 并且 $\textit{ans} \geq a \times 2$,那么这一次枚举可以跳过;如果满足 $a > b$ 并且 $\textit{ans} \geq b \times 2$,那么后续的枚举都可以跳过,直接退出循环。 最后,我们返回答案即可。 为了避免重复计算,我们可以使用记忆化搜索,同时使用剪枝优化枚举的效率。 -时间复杂度 $O(n^3)$,空间复杂度 $O(n^2)$。其中 $n$ 为数组 $stoneValue$ 的长度。 +时间复杂度 $O(n^3)$,空间复杂度 $O(n^2)$。其中 $n$ 为数组 $\textit{stoneValue}$ 的长度。 #### Python3 ```python +def max(a: int, b: int) -> int: + return a if a > b else b + + class Solution: def stoneGameV(self, stoneValue: List[int]) -> int: @cache - def dfs(i, j): - if i == j: + def dfs(i: int, j: int) -> int: + if i >= j: return 0 - ans = a = 0 + ans = l = 0 + r = s[j + 1] - s[i] for k in range(i, j): - a += stoneValue[k] - b = s[j + 1] - s[i] - a - if a < b: - if ans >= a * 2: + l += stoneValue[k] + r -= stoneValue[k] + if l < r: + if ans >= l * 2: continue - ans = max(ans, a + dfs(i, k)) - elif a > b: - if ans >= b * 2: + ans = max(ans, l + dfs(i, k)) + elif l > r: + if ans >= r * 2: break - ans = max(ans, b + dfs(k + 1, j)) + ans = max(ans, r + dfs(k + 1, j)) else: - ans = max(ans, a + dfs(i, k), b + dfs(k + 1, j)) + ans = max(ans, max(l + dfs(i, k), r + dfs(k + 1, j))) return ans s = list(accumulate(stoneValue, initial=0)) @@ -123,44 +128,43 @@ class Solution: class Solution { private int n; private int[] s; - private int[] stoneValue; + private int[] nums; private Integer[][] f; public int stoneGameV(int[] stoneValue) { n = stoneValue.length; - this.stoneValue = stoneValue; s = new int[n + 1]; + nums = stoneValue; + f = new Integer[n][n]; for (int i = 1; i <= n; ++i) { - s[i] = s[i - 1] + stoneValue[i - 1]; + s[i] = s[i - 1] + nums[i - 1]; } - f = new Integer[n][n]; return dfs(0, n - 1); } private int dfs(int i, int j) { - if (i == j) { + if (i >= j) { return 0; } if (f[i][j] != null) { return f[i][j]; } - int ans = 0; - int a = 0; + int ans = 0, l = 0, r = s[j + 1] - s[i]; for (int k = i; k < j; ++k) { - a += stoneValue[k]; - int b = s[j + 1] - s[i] - a; - if (a < b) { - if (ans >= a * 2) { + l += nums[k]; + r -= nums[k]; + if (l < r) { + if (ans > l * 2) { continue; } - ans = Math.max(ans, a + dfs(i, k)); - } else if (a > b) { - if (ans >= b * 2) { + ans = Math.max(ans, l + dfs(i, k)); + } else if (l > r) { + if (ans > r * 2) { break; } - ans = Math.max(ans, b + dfs(k + 1, j)); + ans = Math.max(ans, r + dfs(k + 1, j)); } else { - ans = Math.max(ans, Math.max(a + dfs(i, k), b + dfs(k + 1, j))); + ans = Math.max(ans, Math.max(l + dfs(i, k), r + dfs(k + 1, j))); } } return f[i][j] = ans; @@ -177,35 +181,34 @@ public: int n = stoneValue.size(); int s[n + 1]; s[0] = 0; - for (int i = 1; i <= n; ++i) { - s[i] = s[i - 1] + stoneValue[i - 1]; + for (int i = 0; i < n; i++) { + s[i + 1] = s[i] + stoneValue[i]; } int f[n][n]; - memset(f, 0, sizeof(f)); - function dfs = [&](int i, int j) -> int { - if (i == j) { + memset(f, -1, sizeof(f)); + auto dfs = [&](this auto&& dfs, int i, int j) -> int { + if (i >= j) { return 0; } - if (f[i][j]) { + if (f[i][j] != -1) { return f[i][j]; } - int ans = 0; - int a = 0; + int ans = 0, l = 0, r = s[j + 1] - s[i]; for (int k = i; k < j; ++k) { - a += stoneValue[k]; - int b = s[j + 1] - s[i] - a; - if (a < b) { - if (ans >= a * 2) { + l += stoneValue[k]; + r -= stoneValue[k]; + if (l < r) { + if (ans > l * 2) { continue; } - ans = max(ans, a + dfs(i, k)); - } else if (a > b) { - if (ans >= b * 2) { + ans = max(ans, l + dfs(i, k)); + } else if (l > r) { + if (ans > r * 2) { break; } - ans = max(ans, b + dfs(k + 1, j)); + ans = max(ans, r + dfs(k + 1, j)); } else { - ans = max({ans, a + dfs(i, k), b + dfs(k + 1, j)}); + ans = max({ans, l + dfs(i, k), r + dfs(k + 1, j)}); } } return f[i][j] = ans; @@ -227,31 +230,34 @@ func stoneGameV(stoneValue []int) int { f := make([][]int, n) for i := range f { f[i] = make([]int, n) + for j := range f[i] { + f[i][j] = -1 + } } - var dfs func(i, j int) int + var dfs func(int, int) int dfs = func(i, j int) int { - if i == j { + if i >= j { return 0 } - if f[i][j] != 0 { + if f[i][j] != -1 { return f[i][j] } - ans, a := 0, 0 + ans, l, r := 0, 0, s[j+1]-s[i] for k := i; k < j; k++ { - a += stoneValue[k] - b := s[j+1] - s[i] - a - if a < b { - if ans >= a*2 { + l += stoneValue[k] + r -= stoneValue[k] + if l < r { + if ans > l*2 { continue } - ans = max(ans, a+dfs(i, k)) - } else if a > b { - if ans >= b*2 { + ans = max(ans, dfs(i, k)+l) + } else if l > r { + if ans > r*2 { break } - ans = max(ans, b+dfs(k+1, j)) + ans = max(ans, dfs(k+1, j)+r) } else { - ans = max(ans, max(a+dfs(i, k), b+dfs(k+1, j))) + ans = max(ans, max(dfs(i, k), dfs(k+1, j))+l) } } f[i][j] = ans @@ -261,6 +267,49 @@ func stoneGameV(stoneValue []int) int { } ``` +#### TypeScript + +```ts +function stoneGameV(stoneValue: number[]): number { + const n = stoneValue.length; + const s: number[] = Array(n + 1).fill(0); + for (let i = 0; i < n; i++) { + s[i + 1] = s[i] + stoneValue[i]; + } + const f: number[][] = Array.from({ length: n }, () => Array(n).fill(-1)); + + const dfs = (i: number, j: number): number => { + if (i >= j) { + return 0; + } + if (f[i][j] !== -1) { + return f[i][j]; + } + let [ans, l, r] = [0, 0, s[j + 1] - s[i]]; + for (let k = i; k < j; ++k) { + l += stoneValue[k]; + r -= stoneValue[k]; + if (l < r) { + if (ans > l * 2) { + continue; + } + ans = Math.max(ans, l + dfs(i, k)); + } else if (l > r) { + if (ans > r * 2) { + break; + } + ans = Math.max(ans, r + dfs(k + 1, j)); + } else { + ans = Math.max(ans, l + dfs(i, k), r + dfs(k + 1, j)); + } + } + return (f[i][j] = ans); + }; + + return dfs(0, n - 1); +} +``` + diff --git a/solution/1500-1599/1563.Stone Game V/README_EN.md b/solution/1500-1599/1563.Stone Game V/README_EN.md index 4b4ad760021a2..c5255f765cc1a 100644 --- a/solution/1500-1599/1563.Stone Game V/README_EN.md +++ b/solution/1500-1599/1563.Stone Game V/README_EN.md @@ -68,33 +68,55 @@ The last round Alice has only one choice to divide the row which is [2], [3]. Bo -### Solution 1 +### Solution 1: Memoization + Pruning + +First, we preprocess the prefix sum array $\textit{s}$, where $\textit{s}[i]$ represents the sum of the first $i$ elements of the array $\textit{stoneValue}$. + +Next, we design a function $\textit{dfs}(i, j)$, which represents the maximum score Alice can get from the stones in the subarray $\textit{stoneValue}$ within the index range $[i, j]$. The answer is $\textit{dfs}(0, n - 1)$. + +The calculation process of the function $\textit{dfs}(i, j)$ is as follows: + +- If $i \geq j$, it means there is only one stone left, and Alice cannot split it, so return $0$. +- Otherwise, we enumerate the split point $k$, i.e., $i \leq k < j$, splitting the stones in the subarray $\textit{stoneValue}$ within the index range $[i, j]$ into two parts: $[i, k]$ and $[k + 1, j]$. We calculate $a$ and $b$, which represent the total sum of the stones in the two parts, respectively. Then we calculate $\textit{dfs}(i, k)$ and $\textit{dfs}(k + 1, j)$, and update the answer. + +Note that if $a < b$ and $\textit{ans} \geq a \times 2$, this enumeration can be skipped; if $a > b$ and $\textit{ans} \geq b \times 2$, all subsequent enumerations can be skipped, and the loop can be exited directly. + +Finally, we return the answer. + +To avoid repeated calculations, we can use memoization and pruning to optimize the enumeration efficiency. + +The time complexity is $O(n^3)$, and the space complexity is $O(n^2)$. Here, $n$ is the length of the array $\textit{stoneValue}$. #### Python3 ```python +def max(a: int, b: int) -> int: + return a if a > b else b + + class Solution: def stoneGameV(self, stoneValue: List[int]) -> int: @cache - def dfs(i, j): - if i == j: + def dfs(i: int, j: int) -> int: + if i >= j: return 0 - ans = a = 0 + ans = l = 0 + r = s[j + 1] - s[i] for k in range(i, j): - a += stoneValue[k] - b = s[j + 1] - s[i] - a - if a < b: - if ans >= a * 2: + l += stoneValue[k] + r -= stoneValue[k] + if l < r: + if ans >= l * 2: continue - ans = max(ans, a + dfs(i, k)) - elif a > b: - if ans >= b * 2: + ans = max(ans, l + dfs(i, k)) + elif l > r: + if ans >= r * 2: break - ans = max(ans, b + dfs(k + 1, j)) + ans = max(ans, r + dfs(k + 1, j)) else: - ans = max(ans, a + dfs(i, k), b + dfs(k + 1, j)) + ans = max(ans, max(l + dfs(i, k), r + dfs(k + 1, j))) return ans s = list(accumulate(stoneValue, initial=0)) @@ -107,44 +129,43 @@ class Solution: class Solution { private int n; private int[] s; - private int[] stoneValue; + private int[] nums; private Integer[][] f; public int stoneGameV(int[] stoneValue) { n = stoneValue.length; - this.stoneValue = stoneValue; s = new int[n + 1]; + nums = stoneValue; + f = new Integer[n][n]; for (int i = 1; i <= n; ++i) { - s[i] = s[i - 1] + stoneValue[i - 1]; + s[i] = s[i - 1] + nums[i - 1]; } - f = new Integer[n][n]; return dfs(0, n - 1); } private int dfs(int i, int j) { - if (i == j) { + if (i >= j) { return 0; } if (f[i][j] != null) { return f[i][j]; } - int ans = 0; - int a = 0; + int ans = 0, l = 0, r = s[j + 1] - s[i]; for (int k = i; k < j; ++k) { - a += stoneValue[k]; - int b = s[j + 1] - s[i] - a; - if (a < b) { - if (ans >= a * 2) { + l += nums[k]; + r -= nums[k]; + if (l < r) { + if (ans > l * 2) { continue; } - ans = Math.max(ans, a + dfs(i, k)); - } else if (a > b) { - if (ans >= b * 2) { + ans = Math.max(ans, l + dfs(i, k)); + } else if (l > r) { + if (ans > r * 2) { break; } - ans = Math.max(ans, b + dfs(k + 1, j)); + ans = Math.max(ans, r + dfs(k + 1, j)); } else { - ans = Math.max(ans, Math.max(a + dfs(i, k), b + dfs(k + 1, j))); + ans = Math.max(ans, Math.max(l + dfs(i, k), r + dfs(k + 1, j))); } } return f[i][j] = ans; @@ -161,35 +182,34 @@ public: int n = stoneValue.size(); int s[n + 1]; s[0] = 0; - for (int i = 1; i <= n; ++i) { - s[i] = s[i - 1] + stoneValue[i - 1]; + for (int i = 0; i < n; i++) { + s[i + 1] = s[i] + stoneValue[i]; } int f[n][n]; - memset(f, 0, sizeof(f)); - function dfs = [&](int i, int j) -> int { - if (i == j) { + memset(f, -1, sizeof(f)); + auto dfs = [&](this auto&& dfs, int i, int j) -> int { + if (i >= j) { return 0; } - if (f[i][j]) { + if (f[i][j] != -1) { return f[i][j]; } - int ans = 0; - int a = 0; + int ans = 0, l = 0, r = s[j + 1] - s[i]; for (int k = i; k < j; ++k) { - a += stoneValue[k]; - int b = s[j + 1] - s[i] - a; - if (a < b) { - if (ans >= a * 2) { + l += stoneValue[k]; + r -= stoneValue[k]; + if (l < r) { + if (ans > l * 2) { continue; } - ans = max(ans, a + dfs(i, k)); - } else if (a > b) { - if (ans >= b * 2) { + ans = max(ans, l + dfs(i, k)); + } else if (l > r) { + if (ans > r * 2) { break; } - ans = max(ans, b + dfs(k + 1, j)); + ans = max(ans, r + dfs(k + 1, j)); } else { - ans = max({ans, a + dfs(i, k), b + dfs(k + 1, j)}); + ans = max({ans, l + dfs(i, k), r + dfs(k + 1, j)}); } } return f[i][j] = ans; @@ -211,31 +231,34 @@ func stoneGameV(stoneValue []int) int { f := make([][]int, n) for i := range f { f[i] = make([]int, n) + for j := range f[i] { + f[i][j] = -1 + } } - var dfs func(i, j int) int + var dfs func(int, int) int dfs = func(i, j int) int { - if i == j { + if i >= j { return 0 } - if f[i][j] != 0 { + if f[i][j] != -1 { return f[i][j] } - ans, a := 0, 0 + ans, l, r := 0, 0, s[j+1]-s[i] for k := i; k < j; k++ { - a += stoneValue[k] - b := s[j+1] - s[i] - a - if a < b { - if ans >= a*2 { + l += stoneValue[k] + r -= stoneValue[k] + if l < r { + if ans > l*2 { continue } - ans = max(ans, a+dfs(i, k)) - } else if a > b { - if ans >= b*2 { + ans = max(ans, dfs(i, k)+l) + } else if l > r { + if ans > r*2 { break } - ans = max(ans, b+dfs(k+1, j)) + ans = max(ans, dfs(k+1, j)+r) } else { - ans = max(ans, max(a+dfs(i, k), b+dfs(k+1, j))) + ans = max(ans, max(dfs(i, k), dfs(k+1, j))+l) } } f[i][j] = ans @@ -245,6 +268,49 @@ func stoneGameV(stoneValue []int) int { } ``` +#### TypeScript + +```ts +function stoneGameV(stoneValue: number[]): number { + const n = stoneValue.length; + const s: number[] = Array(n + 1).fill(0); + for (let i = 0; i < n; i++) { + s[i + 1] = s[i] + stoneValue[i]; + } + const f: number[][] = Array.from({ length: n }, () => Array(n).fill(-1)); + + const dfs = (i: number, j: number): number => { + if (i >= j) { + return 0; + } + if (f[i][j] !== -1) { + return f[i][j]; + } + let [ans, l, r] = [0, 0, s[j + 1] - s[i]]; + for (let k = i; k < j; ++k) { + l += stoneValue[k]; + r -= stoneValue[k]; + if (l < r) { + if (ans > l * 2) { + continue; + } + ans = Math.max(ans, l + dfs(i, k)); + } else if (l > r) { + if (ans > r * 2) { + break; + } + ans = Math.max(ans, r + dfs(k + 1, j)); + } else { + ans = Math.max(ans, l + dfs(i, k), r + dfs(k + 1, j)); + } + } + return (f[i][j] = ans); + }; + + return dfs(0, n - 1); +} +``` + diff --git a/solution/1500-1599/1563.Stone Game V/Solution.cpp b/solution/1500-1599/1563.Stone Game V/Solution.cpp index 0578f14071a05..6b0f896a27b1e 100644 --- a/solution/1500-1599/1563.Stone Game V/Solution.cpp +++ b/solution/1500-1599/1563.Stone Game V/Solution.cpp @@ -4,39 +4,38 @@ class Solution { int n = stoneValue.size(); int s[n + 1]; s[0] = 0; - for (int i = 1; i <= n; ++i) { - s[i] = s[i - 1] + stoneValue[i - 1]; + for (int i = 0; i < n; i++) { + s[i + 1] = s[i] + stoneValue[i]; } int f[n][n]; - memset(f, 0, sizeof(f)); - function dfs = [&](int i, int j) -> int { - if (i == j) { + memset(f, -1, sizeof(f)); + auto dfs = [&](this auto&& dfs, int i, int j) -> int { + if (i >= j) { return 0; } - if (f[i][j]) { + if (f[i][j] != -1) { return f[i][j]; } - int ans = 0; - int a = 0; + int ans = 0, l = 0, r = s[j + 1] - s[i]; for (int k = i; k < j; ++k) { - a += stoneValue[k]; - int b = s[j + 1] - s[i] - a; - if (a < b) { - if (ans >= a * 2) { + l += stoneValue[k]; + r -= stoneValue[k]; + if (l < r) { + if (ans > l * 2) { continue; } - ans = max(ans, a + dfs(i, k)); - } else if (a > b) { - if (ans >= b * 2) { + ans = max(ans, l + dfs(i, k)); + } else if (l > r) { + if (ans > r * 2) { break; } - ans = max(ans, b + dfs(k + 1, j)); + ans = max(ans, r + dfs(k + 1, j)); } else { - ans = max({ans, a + dfs(i, k), b + dfs(k + 1, j)}); + ans = max({ans, l + dfs(i, k), r + dfs(k + 1, j)}); } } return f[i][j] = ans; }; return dfs(0, n - 1); } -}; \ No newline at end of file +}; diff --git a/solution/1500-1599/1563.Stone Game V/Solution.go b/solution/1500-1599/1563.Stone Game V/Solution.go index ffcc9b6f58a66..f0eb4f1744449 100644 --- a/solution/1500-1599/1563.Stone Game V/Solution.go +++ b/solution/1500-1599/1563.Stone Game V/Solution.go @@ -7,35 +7,38 @@ func stoneGameV(stoneValue []int) int { f := make([][]int, n) for i := range f { f[i] = make([]int, n) + for j := range f[i] { + f[i][j] = -1 + } } - var dfs func(i, j int) int + var dfs func(int, int) int dfs = func(i, j int) int { - if i == j { + if i >= j { return 0 } - if f[i][j] != 0 { + if f[i][j] != -1 { return f[i][j] } - ans, a := 0, 0 + ans, l, r := 0, 0, s[j+1]-s[i] for k := i; k < j; k++ { - a += stoneValue[k] - b := s[j+1] - s[i] - a - if a < b { - if ans >= a*2 { + l += stoneValue[k] + r -= stoneValue[k] + if l < r { + if ans > l*2 { continue } - ans = max(ans, a+dfs(i, k)) - } else if a > b { - if ans >= b*2 { + ans = max(ans, dfs(i, k)+l) + } else if l > r { + if ans > r*2 { break } - ans = max(ans, b+dfs(k+1, j)) + ans = max(ans, dfs(k+1, j)+r) } else { - ans = max(ans, max(a+dfs(i, k), b+dfs(k+1, j))) + ans = max(ans, max(dfs(i, k), dfs(k+1, j))+l) } } f[i][j] = ans return ans } return dfs(0, n-1) -} \ No newline at end of file +} diff --git a/solution/1500-1599/1563.Stone Game V/Solution.java b/solution/1500-1599/1563.Stone Game V/Solution.java index b0090bea3a3bd..2be6d199784d8 100644 --- a/solution/1500-1599/1563.Stone Game V/Solution.java +++ b/solution/1500-1599/1563.Stone Game V/Solution.java @@ -1,46 +1,45 @@ class Solution { private int n; private int[] s; - private int[] stoneValue; + private int[] nums; private Integer[][] f; public int stoneGameV(int[] stoneValue) { n = stoneValue.length; - this.stoneValue = stoneValue; s = new int[n + 1]; + nums = stoneValue; + f = new Integer[n][n]; for (int i = 1; i <= n; ++i) { - s[i] = s[i - 1] + stoneValue[i - 1]; + s[i] = s[i - 1] + nums[i - 1]; } - f = new Integer[n][n]; return dfs(0, n - 1); } private int dfs(int i, int j) { - if (i == j) { + if (i >= j) { return 0; } if (f[i][j] != null) { return f[i][j]; } - int ans = 0; - int a = 0; + int ans = 0, l = 0, r = s[j + 1] - s[i]; for (int k = i; k < j; ++k) { - a += stoneValue[k]; - int b = s[j + 1] - s[i] - a; - if (a < b) { - if (ans >= a * 2) { + l += nums[k]; + r -= nums[k]; + if (l < r) { + if (ans > l * 2) { continue; } - ans = Math.max(ans, a + dfs(i, k)); - } else if (a > b) { - if (ans >= b * 2) { + ans = Math.max(ans, l + dfs(i, k)); + } else if (l > r) { + if (ans > r * 2) { break; } - ans = Math.max(ans, b + dfs(k + 1, j)); + ans = Math.max(ans, r + dfs(k + 1, j)); } else { - ans = Math.max(ans, Math.max(a + dfs(i, k), b + dfs(k + 1, j))); + ans = Math.max(ans, Math.max(l + dfs(i, k), r + dfs(k + 1, j))); } } return f[i][j] = ans; } -} \ No newline at end of file +} diff --git a/solution/1500-1599/1563.Stone Game V/Solution.py b/solution/1500-1599/1563.Stone Game V/Solution.py index 3f6e0115cb485..ba8123a2f26fc 100644 --- a/solution/1500-1599/1563.Stone Game V/Solution.py +++ b/solution/1500-1599/1563.Stone Game V/Solution.py @@ -1,23 +1,28 @@ +def max(a: int, b: int) -> int: + return a if a > b else b + + class Solution: def stoneGameV(self, stoneValue: List[int]) -> int: @cache - def dfs(i, j): - if i == j: + def dfs(i: int, j: int) -> int: + if i >= j: return 0 - ans = a = 0 + ans = l = 0 + r = s[j + 1] - s[i] for k in range(i, j): - a += stoneValue[k] - b = s[j + 1] - s[i] - a - if a < b: - if ans >= a * 2: + l += stoneValue[k] + r -= stoneValue[k] + if l < r: + if ans >= l * 2: continue - ans = max(ans, a + dfs(i, k)) - elif a > b: - if ans >= b * 2: + ans = max(ans, l + dfs(i, k)) + elif l > r: + if ans >= r * 2: break - ans = max(ans, b + dfs(k + 1, j)) + ans = max(ans, r + dfs(k + 1, j)) else: - ans = max(ans, a + dfs(i, k), b + dfs(k + 1, j)) + ans = max(ans, max(l + dfs(i, k), r + dfs(k + 1, j))) return ans s = list(accumulate(stoneValue, initial=0)) diff --git a/solution/1500-1599/1563.Stone Game V/Solution.ts b/solution/1500-1599/1563.Stone Game V/Solution.ts new file mode 100644 index 0000000000000..716e0dfb95f09 --- /dev/null +++ b/solution/1500-1599/1563.Stone Game V/Solution.ts @@ -0,0 +1,38 @@ +function stoneGameV(stoneValue: number[]): number { + const n = stoneValue.length; + const s: number[] = Array(n + 1).fill(0); + for (let i = 0; i < n; i++) { + s[i + 1] = s[i] + stoneValue[i]; + } + const f: number[][] = Array.from({ length: n }, () => Array(n).fill(-1)); + + const dfs = (i: number, j: number): number => { + if (i >= j) { + return 0; + } + if (f[i][j] !== -1) { + return f[i][j]; + } + let [ans, l, r] = [0, 0, s[j + 1] - s[i]]; + for (let k = i; k < j; ++k) { + l += stoneValue[k]; + r -= stoneValue[k]; + if (l < r) { + if (ans > l * 2) { + continue; + } + ans = Math.max(ans, l + dfs(i, k)); + } else if (l > r) { + if (ans > r * 2) { + break; + } + ans = Math.max(ans, r + dfs(k + 1, j)); + } else { + ans = Math.max(ans, l + dfs(i, k), r + dfs(k + 1, j)); + } + } + return (f[i][j] = ans); + }; + + return dfs(0, n - 1); +}