Skip to content

Commit 7061c5b

Browse files
authored
feat: add solutions to lc problem: No.1931 (doocs#1999)
No.1931.Painting a Grid With Three Different Colors
1 parent 01f1e47 commit 7061c5b

File tree

7 files changed

+890
-0
lines changed

7 files changed

+890
-0
lines changed

solution/1900-1999/1931.Painting a Grid With Three Different Colors/README.md

+307
Original file line numberDiff line numberDiff line change
@@ -48,22 +48,329 @@
4848

4949
<!-- 这里可写通用的实现逻辑 -->
5050

51+
**方法一:状态压缩 + 动态规划**
52+
53+
我们注意到,网格的行数不超过 $5$,那么一列中最多有 $3^5=243$ 种不同的颜色方案。
54+
55+
因此,我们定义 $f[i][j]$ 表示前 $i$ 列中,第 $i$ 列的涂色状态为 $j$ 的方案数。状态 $f[i][j]$ 由 $f[i - 1][k]$ 转移而来,其中 $k$ 是第 $i - 1$ 列的涂色状态,且 $k$ 和 $j$ 满足不同颜色相邻的要求。即:
56+
57+
$$
58+
f[i][j] = \sum_{k \in \text{valid}(j)} f[i - 1][k]
59+
$$
60+
61+
其中 $\text{valid}(j)$ 表示状态 $j$ 的所有合法前驱状态。
62+
63+
最终的答案即为 $f[n][j]$ 的总和,其中 $j$ 是任意合法的状态。
64+
65+
我们注意到,$f[i][j]$ 只和 $f[i - 1][k]$ 有关,因此我们可以使用滚动数组优化空间复杂度。
66+
67+
时间复杂度 $O((m + n) \times 3^{2m})$,空间复杂度 $O(3^m)$。其中 $m$ 和 $n$ 分别是网格的行数和列数。
68+
5169
<!-- tabs:start -->
5270

5371
### **Python3**
5472

5573
<!-- 这里可写当前语言的特殊实现逻辑 -->
5674

5775
```python
76+
class Solution:
77+
def colorTheGrid(self, m: int, n: int) -> int:
78+
def f1(x: int) -> bool:
79+
last = -1
80+
for _ in range(m):
81+
if x % 3 == last:
82+
return False
83+
last = x % 3
84+
x //= 3
85+
return True
86+
87+
def f2(x: int, y: int) -> bool:
88+
for _ in range(m):
89+
if x % 3 == y % 3:
90+
return False
91+
x, y = x // 3, y // 3
92+
return True
5893

94+
mod = 10**9 + 7
95+
mx = 3**m
96+
valid = {i for i in range(mx) if f1(i)}
97+
d = defaultdict(list)
98+
for x in valid:
99+
for y in valid:
100+
if f2(x, y):
101+
d[x].append(y)
102+
f = [int(i in valid) for i in range(mx)]
103+
for _ in range(n - 1):
104+
g = [0] * mx
105+
for i in valid:
106+
for j in d[i]:
107+
g[i] = (g[i] + f[j]) % mod
108+
f = g
109+
return sum(f) % mod
59110
```
60111

61112
### **Java**
62113

63114
<!-- 这里可写当前语言的特殊实现逻辑 -->
64115

65116
```java
117+
class Solution {
118+
private int m;
119+
120+
public int colorTheGrid(int m, int n) {
121+
this.m = m;
122+
final int mod = (int) 1e9 + 7;
123+
int mx = (int) Math.pow(3, m);
124+
Set<Integer> valid = new HashSet<>();
125+
for (int i = 0; i < mx; ++i) {
126+
if (f1(i)) {
127+
valid.add(i);
128+
}
129+
}
130+
Map<Integer, List<Integer>> d = new HashMap<>();
131+
for (int i : valid) {
132+
for (int j : valid) {
133+
if (f2(i, j)) {
134+
d.computeIfAbsent(i, k -> new ArrayList<>()).add(j);
135+
}
136+
}
137+
}
138+
int[] f = new int[mx];
139+
for (int i = 0; i < mx; ++i) {
140+
f[i] = valid.contains(i) ? 1 : 0;
141+
}
142+
for (int k = 1; k < n; ++k) {
143+
int[] g = new int[mx];
144+
for (int i : valid) {
145+
for (int j : d.getOrDefault(i, List.of())) {
146+
g[i] = (g[i] + f[j]) % mod;
147+
}
148+
}
149+
f = g;
150+
}
151+
int ans = 0;
152+
for (int x : f) {
153+
ans = (ans + x) % mod;
154+
}
155+
return ans;
156+
}
157+
158+
private boolean f1(int x) {
159+
int last = -1;
160+
for (int i = 0; i < m; ++i) {
161+
if (x % 3 == last) {
162+
return false;
163+
}
164+
last = x % 3;
165+
x /= 3;
166+
}
167+
return true;
168+
}
169+
170+
private boolean f2(int x, int y) {
171+
for (int i = 0; i < m; ++i) {
172+
if (x % 3 == y % 3) {
173+
return false;
174+
}
175+
x /= 3;
176+
y /= 3;
177+
}
178+
return true;
179+
}
180+
}
181+
```
182+
183+
### **C++**
184+
185+
```cpp
186+
class Solution {
187+
public:
188+
int colorTheGrid(int m, int n) {
189+
auto f1 = [&](int x) {
190+
int last = -1;
191+
for (int i = 0; i < m; ++i) {
192+
if (x % 3 == last) {
193+
return false;
194+
}
195+
last = x % 3;
196+
x /= 3;
197+
}
198+
return true;
199+
};
200+
auto f2 = [&](int x, int y) {
201+
for (int i = 0; i < m; ++i) {
202+
if (x % 3 == y % 3) {
203+
return false;
204+
}
205+
x /= 3;
206+
y /= 3;
207+
}
208+
return true;
209+
};
210+
211+
const int mod = 1e9 + 7;
212+
int mx = pow(3, m);
213+
unordered_set<int> valid;
214+
for (int i = 0; i < mx; ++i) {
215+
if (f1(i)) {
216+
valid.insert(i);
217+
}
218+
}
219+
unordered_map<int, vector<int>> d;
220+
for (int i : valid) {
221+
for (int j : valid) {
222+
if (f2(i, j)) {
223+
d[i].push_back(j);
224+
}
225+
}
226+
}
227+
vector<int> f(mx);
228+
for (int i = 0; i < mx; ++i) {
229+
f[i] = valid.count(i);
230+
}
231+
for (int k = 1; k < n; ++k) {
232+
vector<int> g(mx);
233+
for (int i : valid) {
234+
for (int j : d[i]) {
235+
g[i] = (g[i] + f[j]) % mod;
236+
}
237+
}
238+
f = move(g);
239+
}
240+
int ans = 0;
241+
for (int x : f) {
242+
ans = (ans + x) % mod;
243+
}
244+
return ans;
245+
}
246+
};
247+
```
248+
249+
### **Go**
250+
251+
```go
252+
func colorTheGrid(m int, n int) (ans int) {
253+
f1 := func(x int) bool {
254+
last := -1
255+
for i := 0; i < m; i++ {
256+
if x%3 == last {
257+
return false
258+
}
259+
last = x % 3
260+
x /= 3
261+
}
262+
return true
263+
}
264+
f2 := func(x, y int) bool {
265+
for i := 0; i < m; i++ {
266+
if x%3 == y%3 {
267+
return false
268+
}
269+
x /= 3
270+
y /= 3
271+
}
272+
return true
273+
}
274+
mx := int(math.Pow(3, float64(m)))
275+
valid := map[int]bool{}
276+
for i := 0; i < mx; i++ {
277+
if f1(i) {
278+
valid[i] = true
279+
}
280+
}
281+
d := map[int][]int{}
282+
for i := range valid {
283+
for j := range valid {
284+
if f2(i, j) {
285+
d[i] = append(d[i], j)
286+
}
287+
}
288+
}
289+
f := make([]int, mx)
290+
for i := 0; i < mx; i++ {
291+
if valid[i] {
292+
f[i] = 1
293+
}
294+
}
295+
const mod int = 1e9 + 7
296+
for k := 1; k < n; k++ {
297+
g := make([]int, mx)
298+
for i := range valid {
299+
for _, j := range d[i] {
300+
g[i] = (g[i] + f[j]) % mod
301+
}
302+
}
303+
f = g
304+
}
305+
for _, x := range f {
306+
ans = (ans + x) % mod
307+
}
308+
return
309+
}
310+
```
311+
312+
### **TypeScript**
66313

314+
```ts
315+
function colorTheGrid(m: number, n: number): number {
316+
const f1 = (x: number): boolean => {
317+
let last = -1;
318+
for (let i = 0; i < m; ++i) {
319+
if (x % 3 === last) {
320+
return false;
321+
}
322+
last = x % 3;
323+
x = Math.floor(x / 3);
324+
}
325+
return true;
326+
};
327+
const f2 = (x: number, y: number): boolean => {
328+
for (let i = 0; i < m; ++i) {
329+
if (x % 3 === y % 3) {
330+
return false;
331+
}
332+
x = Math.floor(x / 3);
333+
y = Math.floor(y / 3);
334+
}
335+
return true;
336+
};
337+
const mx = 3 ** m;
338+
const valid = new Set<number>();
339+
for (let i = 0; i < mx; ++i) {
340+
if (f1(i)) {
341+
valid.add(i);
342+
}
343+
}
344+
const d: Map<number, number[]> = new Map();
345+
for (const i of valid) {
346+
for (const j of valid) {
347+
if (f2(i, j)) {
348+
d.set(i, (d.get(i) || []).concat(j));
349+
}
350+
}
351+
}
352+
const f: number[] = Array(mx).fill(0);
353+
for (let i = 0; i < mx; ++i) {
354+
if (valid.has(i)) {
355+
f[i] = 1;
356+
}
357+
}
358+
const mod = 10 ** 9 + 7;
359+
for (let k = 1; k < n; ++k) {
360+
const g: number[] = Array(mx).fill(0);
361+
for (const i of valid) {
362+
for (const j of d.get(i) || []) {
363+
g[i] = (g[i] + f[j]) % mod;
364+
}
365+
}
366+
f.splice(0, f.length, ...g);
367+
}
368+
let ans = 0;
369+
for (const x of f) {
370+
ans = (ans + x) % mod;
371+
}
372+
return ans;
373+
}
67374
```
68375

69376
### **...**

0 commit comments

Comments
 (0)