Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add solutions to lc problem: No.1931 #1999

Merged
merged 1 commit into from
Nov 22, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -48,22 +48,329 @@

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

**方法一:状态压缩 + 动态规划**

我们注意到,网格的行数不超过 $5$,那么一列中最多有 $3^5=243$ 种不同的颜色方案。

因此,我们定义 $f[i][j]$ 表示前 $i$ 列中,第 $i$ 列的涂色状态为 $j$ 的方案数。状态 $f[i][j]$ 由 $f[i - 1][k]$ 转移而来,其中 $k$ 是第 $i - 1$ 列的涂色状态,且 $k$ 和 $j$ 满足不同颜色相邻的要求。即:

$$
f[i][j] = \sum_{k \in \text{valid}(j)} f[i - 1][k]
$$

其中 $\text{valid}(j)$ 表示状态 $j$ 的所有合法前驱状态。

最终的答案即为 $f[n][j]$ 的总和,其中 $j$ 是任意合法的状态。

我们注意到,$f[i][j]$ 只和 $f[i - 1][k]$ 有关,因此我们可以使用滚动数组优化空间复杂度。

时间复杂度 $O((m + n) \times 3^{2m})$,空间复杂度 $O(3^m)$。其中 $m$ 和 $n$ 分别是网格的行数和列数。

<!-- tabs:start -->

### **Python3**

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

```python
class Solution:
def colorTheGrid(self, m: int, n: int) -> int:
def f1(x: int) -> bool:
last = -1
for _ in range(m):
if x % 3 == last:
return False
last = x % 3
x //= 3
return True

def f2(x: int, y: int) -> bool:
for _ in range(m):
if x % 3 == y % 3:
return False
x, y = x // 3, y // 3
return True

mod = 10**9 + 7
mx = 3**m
valid = {i for i in range(mx) if f1(i)}
d = defaultdict(list)
for x in valid:
for y in valid:
if f2(x, y):
d[x].append(y)
f = [int(i in valid) for i in range(mx)]
for _ in range(n - 1):
g = [0] * mx
for i in valid:
for j in d[i]:
g[i] = (g[i] + f[j]) % mod
f = g
return sum(f) % mod
```

### **Java**

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

```java
class Solution {
private int m;

public int colorTheGrid(int m, int n) {
this.m = m;
final int mod = (int) 1e9 + 7;
int mx = (int) Math.pow(3, m);
Set<Integer> valid = new HashSet<>();
for (int i = 0; i < mx; ++i) {
if (f1(i)) {
valid.add(i);
}
}
Map<Integer, List<Integer>> d = new HashMap<>();
for (int i : valid) {
for (int j : valid) {
if (f2(i, j)) {
d.computeIfAbsent(i, k -> new ArrayList<>()).add(j);
}
}
}
int[] f = new int[mx];
for (int i = 0; i < mx; ++i) {
f[i] = valid.contains(i) ? 1 : 0;
}
for (int k = 1; k < n; ++k) {
int[] g = new int[mx];
for (int i : valid) {
for (int j : d.getOrDefault(i, List.of())) {
g[i] = (g[i] + f[j]) % mod;
}
}
f = g;
}
int ans = 0;
for (int x : f) {
ans = (ans + x) % mod;
}
return ans;
}

private boolean f1(int x) {
int last = -1;
for (int i = 0; i < m; ++i) {
if (x % 3 == last) {
return false;
}
last = x % 3;
x /= 3;
}
return true;
}

private boolean f2(int x, int y) {
for (int i = 0; i < m; ++i) {
if (x % 3 == y % 3) {
return false;
}
x /= 3;
y /= 3;
}
return true;
}
}
```

### **C++**

```cpp
class Solution {
public:
int colorTheGrid(int m, int n) {
auto f1 = [&](int x) {
int last = -1;
for (int i = 0; i < m; ++i) {
if (x % 3 == last) {
return false;
}
last = x % 3;
x /= 3;
}
return true;
};
auto f2 = [&](int x, int y) {
for (int i = 0; i < m; ++i) {
if (x % 3 == y % 3) {
return false;
}
x /= 3;
y /= 3;
}
return true;
};

const int mod = 1e9 + 7;
int mx = pow(3, m);
unordered_set<int> valid;
for (int i = 0; i < mx; ++i) {
if (f1(i)) {
valid.insert(i);
}
}
unordered_map<int, vector<int>> d;
for (int i : valid) {
for (int j : valid) {
if (f2(i, j)) {
d[i].push_back(j);
}
}
}
vector<int> f(mx);
for (int i = 0; i < mx; ++i) {
f[i] = valid.count(i);
}
for (int k = 1; k < n; ++k) {
vector<int> g(mx);
for (int i : valid) {
for (int j : d[i]) {
g[i] = (g[i] + f[j]) % mod;
}
}
f = move(g);
}
int ans = 0;
for (int x : f) {
ans = (ans + x) % mod;
}
return ans;
}
};
```

### **Go**

```go
func colorTheGrid(m int, n int) (ans int) {
f1 := func(x int) bool {
last := -1
for i := 0; i < m; i++ {
if x%3 == last {
return false
}
last = x % 3
x /= 3
}
return true
}
f2 := func(x, y int) bool {
for i := 0; i < m; i++ {
if x%3 == y%3 {
return false
}
x /= 3
y /= 3
}
return true
}
mx := int(math.Pow(3, float64(m)))
valid := map[int]bool{}
for i := 0; i < mx; i++ {
if f1(i) {
valid[i] = true
}
}
d := map[int][]int{}
for i := range valid {
for j := range valid {
if f2(i, j) {
d[i] = append(d[i], j)
}
}
}
f := make([]int, mx)
for i := 0; i < mx; i++ {
if valid[i] {
f[i] = 1
}
}
const mod int = 1e9 + 7
for k := 1; k < n; k++ {
g := make([]int, mx)
for i := range valid {
for _, j := range d[i] {
g[i] = (g[i] + f[j]) % mod
}
}
f = g
}
for _, x := range f {
ans = (ans + x) % mod
}
return
}
```

### **TypeScript**

```ts
function colorTheGrid(m: number, n: number): number {
const f1 = (x: number): boolean => {
let last = -1;
for (let i = 0; i < m; ++i) {
if (x % 3 === last) {
return false;
}
last = x % 3;
x = Math.floor(x / 3);
}
return true;
};
const f2 = (x: number, y: number): boolean => {
for (let i = 0; i < m; ++i) {
if (x % 3 === y % 3) {
return false;
}
x = Math.floor(x / 3);
y = Math.floor(y / 3);
}
return true;
};
const mx = 3 ** m;
const valid = new Set<number>();
for (let i = 0; i < mx; ++i) {
if (f1(i)) {
valid.add(i);
}
}
const d: Map<number, number[]> = new Map();
for (const i of valid) {
for (const j of valid) {
if (f2(i, j)) {
d.set(i, (d.get(i) || []).concat(j));
}
}
}
const f: number[] = Array(mx).fill(0);
for (let i = 0; i < mx; ++i) {
if (valid.has(i)) {
f[i] = 1;
}
}
const mod = 10 ** 9 + 7;
for (let k = 1; k < n; ++k) {
const g: number[] = Array(mx).fill(0);
for (const i of valid) {
for (const j of d.get(i) || []) {
g[i] = (g[i] + f[j]) % mod;
}
}
f.splice(0, f.length, ...g);
}
let ans = 0;
for (const x of f) {
ans = (ans + x) % mod;
}
return ans;
}
```

### **...**
Loading