你有一个 n x 3 的网格图 grid ,你需要用 红,黄,绿 三种颜色之一给每一个格子上色,且确保相邻格子颜色不同(也就是有相同水平边或者垂直边的格子颜色不同)。
给你网格图的行数 n 。
请你返回给 grid 涂色的方案数。由于答案可能会非常大,请你返回答案对 10^9 + 7 取余的结果。
示例 1:
输入:n = 1
输出:12
解释:总共有 12 种可行的方法:
示例 2:
输入:n = 2
输出:54
示例 3:
输入:n = 3
输出:246
示例 4:
输入:n = 7
输出:106494
示例 5:
输入:n = 5000
输出:30228214
提示:
n == grid.length
grid[i].length == 3
1 <= n <= 5000
思路:定义dp[i][j][k][h]:表示第i行状态为(j, k, h)时的方案数,其中j,k,h只能取0,1,2分别表示三种颜色。
进一步优化:因为第i行只和第i-1行有关,因此我们可以将dp数组的第一维变为2(PS:我懒得弄了)。
class Solution {
public int numOfWays(int n) {
int mod=1000000007;
long[][][][] dp=new long[n+1][3][3][3];
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
for(int k=0;k<3;k++) {
if(i==j || j==k) continue;
dp[1][i][j][k]=1;
}
for(int i=2;i<=n;i++) {
for(int ii=0;ii<3;ii++)
for(int jj=0;jj<3;jj++)
for(int kk=0;kk<3;kk++) {
if(ii==jj || jj==kk) continue;
for(int iii=0;iii<3;iii++)
for(int jjj=0;jjj<3;jjj++)
for(int kkk=0;kkk<3;kkk++) {
if(iii==jjj || jjj==kkk)
continue;
if(iii==ii || jjj==jj || kkk==kk)
continue;
dp[i][ii][jj][kk]=(dp[i][ii][jj][kk]+dp[i-1][iii][jjj][kkk])%mod;
}
}
}
long ans=0;
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
for(int k=0;k<3;k++) {
if(i==j || j==k) continue;
ans=(ans+dp[n][i][j][k])%mod;
}
return (int)ans;
}
}