@@ -69,48 +69,53 @@ tags:
6969
7070### 方法一:记忆化搜索 + 剪枝
7171
72- 我们先预处理出前缀和数组 $s $,其中 $s [ i] $ 表示数组 $stoneValue$ 前 $i$ 个元素的和。
72+ 我们先预处理出前缀和数组 $\textit{s} $,其中 $\textit{s} [ i] $ 表示数组 $\textit{ stoneValue} $ 前 $i$ 个元素的和。
7373
74- 接下来,我们设计一个函数 $dfs(i, j)$,表示数组 $stoneValue$ 中下标范围 $[ i, j] $ 内的石子,Alice 能够获得的最大分数。那么答案就是 $dfs(0, n - 1)$。
74+ 接下来,我们设计一个函数 $\textit{ dfs} (i, j)$,表示数组 $\textit{ stoneValue} $ 中下标范围 $[ i, j] $ 内的石子,Alice 能够获得的最大分数。那么答案就是 $\textit{ dfs} (0, n - 1)$。
7575
76- 函数 $dfs(i, j)$ 的计算过程如下:
76+ 函数 $\textit{ dfs} (i, j)$ 的计算过程如下:
7777
78- - 如果 $i = j$,说明只剩下一块石子,Alice 无法进行分割,因此返回 $0$。
79- - 否则,我们枚举分割点 $k$,即 $i \leq k \lt j$,将数组 $stoneValue$ 中下标范围 $[ i, j] $ 内的石子分割为 $[ i, k] $ 和 $[ k + 1, j] $ 两部分,计算出 $a$ 和 $b$,分别表示两部分的石子总和。然后我们分别计算 $dfs(i, k)$ 和 $dfs(k + 1, j)$,并更新答案。
78+ - 如果 $i \geq j$,说明只剩下一块石子,Alice 无法进行分割,因此返回 $0$。
79+ - 否则,我们枚举分割点 $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)$,并更新答案。
8080
81- 注意,如果满足 $a \lt b$ 并且 $ans \geq a \times 2$,那么这一次枚举可以跳过;如果满足 $a \gt b$ 并且 $ans \geq b \times 2$,那么后续的枚举都可以跳过,直接退出循环。
81+ 注意,如果满足 $a < b$ 并且 $\textit{ ans} \geq a \times 2$,那么这一次枚举可以跳过;如果满足 $a > b$ 并且 $\textit{ ans} \geq b \times 2$,那么后续的枚举都可以跳过,直接退出循环。
8282
8383最后,我们返回答案即可。
8484
8585为了避免重复计算,我们可以使用记忆化搜索,同时使用剪枝优化枚举的效率。
8686
87- 时间复杂度 $O(n^3)$,空间复杂度 $O(n^2)$。其中 $n$ 为数组 $stoneValue$ 的长度。
87+ 时间复杂度 $O(n^3)$,空间复杂度 $O(n^2)$。其中 $n$ 为数组 $\textit{ stoneValue} $ 的长度。
8888
8989<!-- tabs:start -->
9090
9191#### Python3
9292
9393``` python
94+ def max (a : int , b : int ) -> int :
95+ return a if a > b else b
96+
97+
9498class Solution :
9599 def stoneGameV (self , stoneValue : List[int ]) -> int :
96100 @cache
97- def dfs (i , j ) :
98- if i = = j:
101+ def dfs (i : int , j : int ) -> int :
102+ if i > = j:
99103 return 0
100- ans = a = 0
104+ ans = l = 0
105+ r = s[j + 1 ] - s[i]
101106 for k in range (i, j):
102- a += stoneValue[k]
103- b = s[j + 1 ] - s[i] - a
104- if a < b :
105- if ans >= a * 2 :
107+ l += stoneValue[k]
108+ r -= stoneValue[k]
109+ if l < r :
110+ if ans >= l * 2 :
106111 continue
107- ans = max (ans, a + dfs(i, k))
108- elif a > b :
109- if ans >= b * 2 :
112+ ans = max (ans, l + dfs(i, k))
113+ elif l > r :
114+ if ans >= r * 2 :
110115 break
111- ans = max (ans, b + dfs(k + 1 , j))
116+ ans = max (ans, r + dfs(k + 1 , j))
112117 else :
113- ans = max (ans, a + dfs(i, k), b + dfs(k + 1 , j))
118+ ans = max (ans, max (l + dfs(i, k), r + dfs(k + 1 , j) ))
114119 return ans
115120
116121 s = list (accumulate(stoneValue, initial = 0 ))
@@ -123,44 +128,43 @@ class Solution:
123128class Solution {
124129 private int n;
125130 private int [] s;
126- private int [] stoneValue ;
131+ private int [] nums ;
127132 private Integer [][] f;
128133
129134 public int stoneGameV (int [] stoneValue ) {
130135 n = stoneValue. length;
131- this . stoneValue = stoneValue;
132136 s = new int [n + 1 ];
137+ nums = stoneValue;
138+ f = new Integer [n][n];
133139 for (int i = 1 ; i <= n; ++ i) {
134- s[i] = s[i - 1 ] + stoneValue [i - 1 ];
140+ s[i] = s[i - 1 ] + nums [i - 1 ];
135141 }
136- f = new Integer [n][n];
137142 return dfs(0 , n - 1 );
138143 }
139144
140145 private int dfs (int i , int j ) {
141- if (i = = j) {
146+ if (i > = j) {
142147 return 0 ;
143148 }
144149 if (f[i][j] != null ) {
145150 return f[i][j];
146151 }
147- int ans = 0 ;
148- int a = 0 ;
152+ int ans = 0 , l = 0 , r = s[j + 1 ] - s[i];
149153 for (int k = i; k < j; ++ k) {
150- a += stoneValue [k];
151- int b = s[j + 1 ] - s[i] - a ;
152- if (a < b ) {
153- if (ans >= a * 2 ) {
154+ l += nums [k];
155+ r -= nums[k] ;
156+ if (l < r ) {
157+ if (ans > l * 2 ) {
154158 continue ;
155159 }
156- ans = Math . max(ans, a + dfs(i, k));
157- } else if (a > b ) {
158- if (ans >= b * 2 ) {
160+ ans = Math . max(ans, l + dfs(i, k));
161+ } else if (l > r ) {
162+ if (ans > r * 2 ) {
159163 break ;
160164 }
161- ans = Math . max(ans, b + dfs(k + 1 , j));
165+ ans = Math . max(ans, r + dfs(k + 1 , j));
162166 } else {
163- ans = Math . max(ans, Math . max(a + dfs(i, k), b + dfs(k + 1 , j)));
167+ ans = Math . max(ans, Math . max(l + dfs(i, k), r + dfs(k + 1 , j)));
164168 }
165169 }
166170 return f[i][j] = ans;
@@ -177,35 +181,34 @@ public:
177181 int n = stoneValue.size();
178182 int s[ n + 1] ;
179183 s[ 0] = 0;
180- for (int i = 1 ; i <= n; ++i ) {
181- s[ i] = s[ i - 1 ] + stoneValue[ i - 1 ] ;
184+ for (int i = 0 ; i < n; i++ ) {
185+ s[ i + 1 ] = s[ i] + stoneValue[ i] ;
182186 }
183187 int f[ n] [ n ] ;
184- memset(f, 0 , sizeof(f));
185- function<int(int, int)> dfs = [ &] (int i, int j) -> int {
186- if (i = = j) {
188+ memset(f, -1 , sizeof(f));
189+ auto dfs = [ &] (this auto&& dfs, int i, int j) -> int {
190+ if (i > = j) {
187191 return 0;
188192 }
189- if (f[ i] [ j ] ) {
193+ if (f[ i] [ j ] != -1 ) {
190194 return f[ i] [ j ] ;
191195 }
192- int ans = 0;
193- int a = 0;
196+ int ans = 0, l = 0, r = s[ j + 1] - s[ i] ;
194197 for (int k = i; k < j; ++k) {
195- a += stoneValue[ k] ;
196- int b = s [ j + 1 ] - s [ i ] - a ;
197- if (a < b ) {
198- if (ans >= a * 2) {
198+ l += stoneValue[ k] ;
199+ r -= stoneValue [ k ] ;
200+ if (l < r ) {
201+ if (ans > l * 2) {
199202 continue;
200203 }
201- ans = max(ans, a + dfs(i, k));
202- } else if (a > b ) {
203- if (ans >= b * 2) {
204+ ans = max(ans, l + dfs(i, k));
205+ } else if (l > r ) {
206+ if (ans > r * 2) {
204207 break;
205208 }
206- ans = max(ans, b + dfs(k + 1, j));
209+ ans = max(ans, r + dfs(k + 1, j));
207210 } else {
208- ans = max({ans, a + dfs(i, k), b + dfs(k + 1, j)});
211+ ans = max({ans, l + dfs(i, k), r + dfs(k + 1, j)});
209212 }
210213 }
211214 return f[ i] [ j ] = ans;
@@ -227,31 +230,34 @@ func stoneGameV(stoneValue []int) int {
227230 f := make([][]int, n)
228231 for i := range f {
229232 f[i] = make([]int, n)
233+ for j := range f[i] {
234+ f[i][j] = -1
235+ }
230236 }
231- var dfs func(i, j int) int
237+ var dfs func(int, int) int
232238 dfs = func(i, j int) int {
233- if i = = j {
239+ if i > = j {
234240 return 0
235241 }
236- if f[i][j] != 0 {
242+ if f[i][j] != -1 {
237243 return f[i][j]
238244 }
239- ans, a := 0, 0
245+ ans, l, r := 0, 0, s[j+1]-s[i]
240246 for k := i; k < j; k++ {
241- a += stoneValue[k]
242- b := s[j+1] - s[i] - a
243- if a < b {
244- if ans >= a *2 {
247+ l += stoneValue[k]
248+ r -= stoneValue[k]
249+ if l < r {
250+ if ans > l *2 {
245251 continue
246252 }
247- ans = max(ans, a+ dfs(i, k))
248- } else if a > b {
249- if ans >= b *2 {
253+ ans = max(ans, dfs(i, k)+l )
254+ } else if l > r {
255+ if ans > r *2 {
250256 break
251257 }
252- ans = max(ans, b+ dfs(k+1, j))
258+ ans = max(ans, dfs(k+1, j)+r )
253259 } else {
254- ans = max(ans, max(a+ dfs(i, k), b+ dfs(k+1, j)))
260+ ans = max(ans, max(dfs(i, k), dfs(k+1, j))+l )
255261 }
256262 }
257263 f[i][j] = ans
@@ -261,6 +267,49 @@ func stoneGameV(stoneValue []int) int {
261267}
262268```
263269
270+ #### TypeScript
271+
272+ ``` ts
273+ function stoneGameV(stoneValue : number []): number {
274+ const n = stoneValue .length ;
275+ const s: number [] = Array (n + 1 ).fill (0 );
276+ for (let i = 0 ; i < n ; i ++ ) {
277+ s [i + 1 ] = s [i ] + stoneValue [i ];
278+ }
279+ const f: number [][] = Array .from ({ length: n }, () => Array (n ).fill (- 1 ));
280+
281+ const dfs = (i : number , j : number ): number => {
282+ if (i >= j ) {
283+ return 0 ;
284+ }
285+ if (f [i ][j ] !== - 1 ) {
286+ return f [i ][j ];
287+ }
288+ let [ans, l, r] = [0 , 0 , s [j + 1 ] - s [i ]];
289+ for (let k = i ; k < j ; ++ k ) {
290+ l += stoneValue [k ];
291+ r -= stoneValue [k ];
292+ if (l < r ) {
293+ if (ans > l * 2 ) {
294+ continue ;
295+ }
296+ ans = Math .max (ans , l + dfs (i , k ));
297+ } else if (l > r ) {
298+ if (ans > r * 2 ) {
299+ break ;
300+ }
301+ ans = Math .max (ans , r + dfs (k + 1 , j ));
302+ } else {
303+ ans = Math .max (ans , l + dfs (i , k ), r + dfs (k + 1 , j ));
304+ }
305+ }
306+ return (f [i ][j ] = ans );
307+ };
308+
309+ return dfs (0 , n - 1 );
310+ }
311+ ```
312+
264313<!-- tabs: end -->
265314
266315<!-- solution: end -->
0 commit comments