2020-04-12 20:44:30
问题描述:
你有一个 n x 3 的网格图 grid ,你需要用 红,黄,绿 三种颜色之一给每一个格子上色,且确保相邻格子颜色不同(也就是有相同水平边或者垂直边的格子颜色不同)。
给你网格图的行数 n 。
请你返回给 grid 涂色的方案数。由于答案可能会非常大,请你返回答案对 10^9 + 7 取余的结果。
示例 1:
输入:n = 1 输出:12 解释:总共有 12 种可行的方法:
提示:
n == grid.length
grid[i].length == 3
1 <= n <= 5000
问题求解:
可以使用状态压缩来进行求解,主要难点在于这里是三状态的,需要使用2bit来进行表示。
时间复杂度:O(n * 64 * 64)
int[][] dp = new int[5050][64]; int mod = (int)1e9 + 7; public int numOfWays(int n) { for (int i = 0; i < 64; i++) { int c1 = get_color(i, 0); int c2 = get_color(i, 1); int c3 = get_color(i, 2); if (c1 == 3 || c2 == 3 || c3 == 3) continue; if (c1 == c2 || c2 == c3) continue; dp[0][i] = 1; } for (int i = 1; i < n; i++) { for (int curr = 0; curr < 64; curr++) { int c1 = get_color(curr, 0); int c2 = get_color(curr, 1); int c3 = get_color(curr, 2); if (c1 == 3 || c2 == 3 || c3 == 3) continue; if (c1 == c2 || c2 == c3) continue; for (int prev = 0; prev < 64; prev++) { int v1 = get_color(prev, 0); int v2 = get_color(prev, 1); int v3 = get_color(prev, 2); if (v1 == 3 || v2 == 3 || v3 == 3) continue; if (v1 == v2 || v2 == v3) continue; if (v1 == c1 || v2 == c2 || v3 == c3) continue; dp[i][curr] = (dp[i][curr] + dp[i - 1][prev]) % mod; } } } int res = 0; for (int i = 0; i < 64; i++) { res = (res + dp[n - 1][i]) % mod; } return res; } private int get_color(int num, int idx) { return (num >> 2 * idx) & 3; }