67
67
- 当状态为 $010$ 型时:下一行可能的状态为:$101$, $102$, $121$, $201$, $202$。这 $5$ 个状态可归纳为 $3$ 个 $010$ 型,$2$ 个 $012$ 型。
68
68
- 当状态为 $012$ 型时:下一行可能的状态为:$101$, $120$, $121$, $201$。这 $4$ 个状态可归纳为 $2$ 个 $010$ 型,$2$ 个 $012$ 型。
69
69
70
- 综上所述,可以得到:$newf0 = 3 * f0 + 2 * f1$, $newf1 = 2 * f0 + 2 * f1$。
70
+ 综上所述,可以得到:$newf0 = 3 \times f0 + 2 \times f1$, $newf1 = 2 \times f0 + 2 \times f1$。
71
71
72
- 时间复杂度 $O(n)$。
72
+ 时间复杂度 $O(n)$,其中 $n$ 是网格的行数。空间复杂度 $O(1)$。
73
+
74
+ ** 方法二:状态压缩 + 动态规划**
75
+
76
+ 我们注意到,网格只有 $3$ 列,那么一行中最多有 $3^3=27$ 种不同的涂色方案。
77
+
78
+ 因此,我们定义 $f[ i] [ j ] $ 表示前 $i$ 行中,第 $i$ 行的涂色状态为 $j$ 的方案数。状态 $f[ i] [ j ] $ 由 $f[ i - 1] [ k ] $ 转移而来,其中 $k$ 是第 $i - 1$ 行的涂色状态,且 $k$ 和 $j$ 满足不同颜色相邻的要求。即:
79
+
80
+ $$
81
+ f[i][j] = \sum_{k \in \text{valid}(j)} f[i - 1][k]
82
+ $$
83
+
84
+ 其中 $\text{valid}(j)$ 表示状态 $j$ 的所有合法前驱状态。
85
+
86
+ 最终的答案即为 $f[ n] [ j ] $ 的总和,其中 $j$ 是任意合法的状态。
87
+
88
+ 我们注意到,$f[ i] [ j ] $ 只和 $f[ i - 1] [ k ] $ 有关,因此我们可以使用滚动数组优化空间复杂度。
89
+
90
+ 时间复杂度 $O((m + n) \times 3^{2m})$,空间复杂度 $O(3^m)$。其中 $n$ 和 $m$ 分别是网格的行数和列数。
73
91
74
92
<!-- tabs:start -->
75
93
@@ -89,6 +107,44 @@ class Solution:
89
107
return (f0 + f1) % mod
90
108
```
91
109
110
+ ``` python
111
+ class Solution :
112
+ def numOfWays (self , n : int ) -> int :
113
+ def f1 (x : int ) -> bool :
114
+ last = - 1
115
+ for _ in range (3 ):
116
+ if x % 3 == last:
117
+ return False
118
+ last = x % 3
119
+ x //= 3
120
+ return True
121
+
122
+ def f2 (x : int , y : int ) -> bool :
123
+ for _ in range (3 ):
124
+ if x % 3 == y % 3 :
125
+ return False
126
+ x //= 3
127
+ y //= 3
128
+ return True
129
+
130
+ mod = 10 ** 9 + 7
131
+ m = 27
132
+ valid = {i for i in range (m) if f1(i)}
133
+ d = defaultdict(list )
134
+ for i in valid:
135
+ for j in valid:
136
+ if f2(i, j):
137
+ d[i].append(j)
138
+ f = [int (i in valid) for i in range (m)]
139
+ for _ in range (n - 1 ):
140
+ g = [0 ] * m
141
+ for i in valid:
142
+ for j in d[i]:
143
+ g[j] = (g[j] + f[i]) % mod
144
+ f = g
145
+ return sum (f) % mod
146
+ ```
147
+
92
148
### ** Java**
93
149
94
150
<!-- 这里可写当前语言的特殊实现逻辑 -->
@@ -109,6 +165,68 @@ class Solution {
109
165
}
110
166
```
111
167
168
+ ``` java
169
+ class Solution {
170
+ public int numOfWays (int n ) {
171
+ final int mod = (int ) 1e9 + 7 ;
172
+ int m = 27 ;
173
+ Set<Integer > valid = new HashSet<> ();
174
+ int [] f = new int [m];
175
+ for (int i = 0 ; i < m; ++ i) {
176
+ if (f1(i)) {
177
+ valid. add(i);
178
+ f[i] = 1 ;
179
+ }
180
+ }
181
+ Map<Integer , List<Integer > > d = new HashMap<> ();
182
+ for (int i : valid) {
183
+ for (int j : valid) {
184
+ if (f2(i, j)) {
185
+ d. computeIfAbsent(i, k - > new ArrayList<> ()). add(j);
186
+ }
187
+ }
188
+ }
189
+ for (int k = 1 ; k < n; ++ k) {
190
+ int [] g = new int [m];
191
+ for (int i : valid) {
192
+ for (int j : d. getOrDefault(i, List . of())) {
193
+ g[j] = (g[j] + f[i]) % mod;
194
+ }
195
+ }
196
+ f = g;
197
+ }
198
+ int ans = 0 ;
199
+ for (int x : f) {
200
+ ans = (ans + x) % mod;
201
+ }
202
+ return ans;
203
+ }
204
+
205
+ private boolean f1 (int x ) {
206
+ int last = - 1 ;
207
+ for (int i = 0 ; i < 3 ; ++ i) {
208
+ if (x % 3 == last) {
209
+ return false ;
210
+ }
211
+ last = x % 3 ;
212
+ x /= 3 ;
213
+ }
214
+ return true ;
215
+ }
216
+
217
+ private boolean f2 (int x , int y ) {
218
+ for (int i = 0 ; i < 3 ; ++ i) {
219
+ if (x % 3 == y % 3 ) {
220
+ return false ;
221
+ }
222
+ x /= 3 ;
223
+ y /= 3 ;
224
+ }
225
+ return true ;
226
+ }
227
+ }
228
+ ```
229
+
112
230
### ** C++**
113
231
114
232
``` cpp
@@ -130,6 +248,69 @@ public:
130
248
};
131
249
```
132
250
251
+ ```cpp
252
+ class Solution {
253
+ public:
254
+ int numOfWays(int n) {
255
+ int m = 27;
256
+
257
+ auto f1 = [&](int x) {
258
+ int last = -1;
259
+ for (int i = 0; i < 3; ++i) {
260
+ if (x % 3 == last) {
261
+ return false;
262
+ }
263
+ last = x % 3;
264
+ x /= 3;
265
+ }
266
+ return true;
267
+ };
268
+ auto f2 = [&](int x, int y) {
269
+ for (int i = 0; i < 3; ++i) {
270
+ if (x % 3 == y % 3) {
271
+ return false;
272
+ }
273
+ x /= 3;
274
+ y /= 3;
275
+ }
276
+ return true;
277
+ };
278
+
279
+ const int mod = 1e9 + 7;
280
+ unordered_set<int> valid;
281
+ vector<int> f(m);
282
+ for (int i = 0; i < m; ++i) {
283
+ if (f1(i)) {
284
+ valid.insert(i);
285
+ f[i] = 1;
286
+ }
287
+ }
288
+ unordered_map<int, vector<int>> d;
289
+ for (int i : valid) {
290
+ for (int j : valid) {
291
+ if (f2(i, j)) {
292
+ d[i].push_back(j);
293
+ }
294
+ }
295
+ }
296
+ for (int k = 1; k < n; ++k) {
297
+ vector<int> g(m);
298
+ for (int i : valid) {
299
+ for (int j : d[i]) {
300
+ g[j] = (g[j] + f[i]) % mod;
301
+ }
302
+ }
303
+ f = move(g);
304
+ }
305
+ int ans = 0;
306
+ for (int x : f) {
307
+ ans = (ans + x) % mod;
308
+ }
309
+ return ans;
310
+ }
311
+ };
312
+ ```
313
+
133
314
### ** Go**
134
315
135
316
``` go
@@ -146,6 +327,140 @@ func numOfWays(n int) int {
146
327
}
147
328
```
148
329
330
+ ``` go
331
+ func numOfWays (n int ) (ans int ) {
332
+ f1 := func (x int ) bool {
333
+ last := -1
334
+ for i := 0 ; i < 3 ; i++ {
335
+ if x%3 == last {
336
+ return false
337
+ }
338
+ last = x % 3
339
+ x /= 3
340
+ }
341
+ return true
342
+ }
343
+ f2 := func (x, y int ) bool {
344
+ for i := 0 ; i < 3 ; i++ {
345
+ if x%3 == y%3 {
346
+ return false
347
+ }
348
+ x /= 3
349
+ y /= 3
350
+ }
351
+ return true
352
+ }
353
+ m := 27
354
+ valid := map [int ]bool {}
355
+ f := make ([]int , m)
356
+ for i := 0 ; i < m; i++ {
357
+ if f1 (i) {
358
+ valid[i] = true
359
+ f[i] = 1
360
+ }
361
+ }
362
+ d := map [int ][]int {}
363
+ for i := range valid {
364
+ for j := range valid {
365
+ if f2 (i, j) {
366
+ d[i] = append (d[i], j)
367
+ }
368
+ }
369
+ }
370
+ const mod int = 1e9 + 7
371
+ for k := 1 ; k < n; k++ {
372
+ g := make ([]int , m)
373
+ for i := range valid {
374
+ for _ , j := range d[i] {
375
+ g[i] = (g[i] + f[j]) % mod
376
+ }
377
+ }
378
+ f = g
379
+ }
380
+ for _ , x := range f {
381
+ ans = (ans + x) % mod
382
+ }
383
+ return
384
+ }
385
+ ```
386
+
387
+ ### ** TypeScript**
388
+
389
+ ``` ts
390
+ function numOfWays(n : number ): number {
391
+ const mod: number = 10 ** 9 + 7 ;
392
+ let f0: number = 6 ;
393
+ let f1: number = 6 ;
394
+
395
+ for (let i = 1 ; i < n ; i ++ ) {
396
+ const g0: number = (3 * f0 + 2 * f1 ) % mod ;
397
+ const g1: number = (2 * f0 + 2 * f1 ) % mod ;
398
+ f0 = g0 ;
399
+ f1 = g1 ;
400
+ }
401
+
402
+ return (f0 + f1 ) % mod ;
403
+ }
404
+ ```
405
+
406
+ ``` ts
407
+ function numOfWays(n : number ): number {
408
+ const f1 = (x : number ): boolean => {
409
+ let last = - 1 ;
410
+ for (let i = 0 ; i < 3 ; ++ i ) {
411
+ if (x % 3 === last ) {
412
+ return false ;
413
+ }
414
+ last = x % 3 ;
415
+ x = Math .floor (x / 3 );
416
+ }
417
+ return true ;
418
+ };
419
+ const f2 = (x : number , y : number ): boolean => {
420
+ for (let i = 0 ; i < 3 ; ++ i ) {
421
+ if (x % 3 === y % 3 ) {
422
+ return false ;
423
+ }
424
+ x = Math .floor (x / 3 );
425
+ y = Math .floor (y / 3 );
426
+ }
427
+ return true ;
428
+ };
429
+ const m = 27 ;
430
+ const valid = new Set <number >();
431
+ const f: number [] = Array (m ).fill (0 );
432
+ for (let i = 0 ; i < m ; ++ i ) {
433
+ if (f1 (i )) {
434
+ valid .add (i );
435
+ f [i ] = 1 ;
436
+ }
437
+ }
438
+ const d: Map <number , number []> = new Map ();
439
+ for (const i of valid ) {
440
+ for (const j of valid ) {
441
+ if (f2 (i , j )) {
442
+ d .set (i , (d .get (i ) || []).concat (j ));
443
+ }
444
+ }
445
+ }
446
+ const mod = 10 ** 9 + 7 ;
447
+ for (let k = 1 ; k < n ; ++ k ) {
448
+ const g: number [] = Array (m ).fill (0 );
449
+ for (const i of valid ) {
450
+ for (const j of d .get (i ) || []) {
451
+ g [i ] = (g [i ] + f [j ]) % mod ;
452
+ }
453
+ }
454
+ f .splice (0 , f .length , ... g );
455
+ }
456
+ let ans = 0 ;
457
+ for (const x of f ) {
458
+ ans = (ans + x ) % mod ;
459
+ }
460
+ return ans ;
461
+ }
462
+ ```
463
+
149
464
### ** ...**
150
465
151
466
```
0 commit comments