You are given two integers m and n. Consider an m x n grid where each cell is initially white. You can paint each cell red, green, or blue. All cells must be painted.
Return the number of ways to color the grid with no two adjacent cells having the same color. Since the answer can be very large, return it modulo10^9 + 7.
To solve this problem, we use dynamic programming with state compression. Here’s a detailed explanation of the approach:
Problem Analysis:
We need to calculate the number of valid ways to colour an m x n grid such that no two adjacent cells (vertically or horizontally) have the same colour.
Colours are limited to red, green, and blue.
Key Insight:
For a fixed number of rows m, we can precompute all valid row patterns where no two adjacent cells in a row have the same colours.
To transition from one column to another, we compute which row patterns are valid to follow a given row pattern in terms of maintaining “no adjacent colour conflict” vertically.
Dynamic Programming:
Let prev represent the row pattern for column j - 1 and curr represent the row pattern for column j.
We calculate the number of ways to assign valid colours column by column, keeping track of compatible row patterns between adjacent columns.
Modulo Operation: Since the result can be large, we compute the result modulo 10^9 + 7.
classSolution {
publicintcolorTheGrid(int m, int n) {
finalint MOD = 1000000007;
// List to store all valid row patterns List<Integer> patterns =new ArrayList<>();
generatePatterns(m, 0, 0, patterns);
// Number of patternsint k = patterns.size();
// Build compatibility listboolean[][] compatible =newboolean[k][k];
for (int i = 0; i < k; i++) {
for (int j = 0; j < k; j++) {
compatible[i][j]= isCompatible(
patterns.get(i),
patterns.get(j),
m
);
}
}
// DP arrayint[] dp =newint[k];
Arrays.fill(dp, 1);
// Transition for each columnfor (int col = 1; col < n; col++) {
int[] newDp =newint[k];
for (int i = 0; i < k; i++) {
for (int j = 0; j < k; j++) {
if (compatible[i][j]) {
newDp[i]= (newDp[i]+ dp[j]) % MOD;
}
}
}
dp = newDp;
}
// Sum up all the ways to paint the gridint ans = 0;
for (int x : dp) {
ans = (ans + x) % MOD;
}
return ans;
}
// Helper method to generate valid patterns for a single columnprivatevoidgeneratePatterns(
int m,
int curr,
int pos,
List<Integer> patterns
) {
if (pos == m) {
patterns.add(curr);
return;
}
for (int i = 0; i < 3; i++) {
if (pos == 0 || (curr % 3) != i) { // Ensure no adjacent cells have the same colour generatePatterns(m, curr * 3 + i, pos + 1, patterns);
}
}
}
// Helper method to check if two patterns are vertically compatibleprivatebooleanisCompatible(int p1, int p2, int m) {
for (int i = 0; i < m; i++) {
if ((p1 % 3) == (p2 % 3)) { // Conflict if colours are the samereturnfalse;
}
p1 /= 3;
p2 /= 3;
}
returntrue;
}
}
classSolution:
MOD =10**9+7defcolorTheGrid(self, m: int, n: int) -> int:
# Generate all valid patterns for one columndefgenerate_patterns(pos: int, curr: int) -> List[int]:
if pos == m:
patterns.append(curr)
returnfor c in range(3):
if pos ==0or c != curr %3:
generate_patterns(pos +1, curr *3+ c)
defis_compatible(p1: int, p2: int) -> bool:
for _ in range(m):
if p1 %3== p2 %3:
returnFalse p1 //=3 p2 //=3returnTrue# Precompute valid column patterns and compatibility patterns: List[int] = []
generate_patterns(0, 0)
k = len(patterns)
compatibility = [[is_compatible(p1, p2) for p2 in patterns] for p1 in patterns]
# Initialize DP, one column at a time dp: List[int] = [1] * k
for _ in range(1, n):
new_dp = [0] * k
for i in range(k):
for j in range(k):
if compatibility[i][j]:
new_dp[i] = (new_dp[i] + dp[j]) % self.MOD
dp = new_dp
# Return total countreturn sum(dp) % self.MOD