[LeetCode in Python] 5383 (H) number of ways to paint n x 3 grid 给 N x 3 网格图涂色的方案数
题目:
https://leetcode-cn.com/problems/number-of-ways-to-paint-n-x-3-grid/
你有一个 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
解题思路
- 使用数学方法当然是最销魂的,咱还是用简单粗暴的方法吧。
- 显而易见,只要确定了相邻两行的转换关系,剩下的就是迭代了。
- 手写第一行的模式,只有12个,多乎哉?不多也。
- 然后穷举遍历,得到这12个模式对应的全部可能的下一行模式,存为next字典备用。
- 将第一行的模式存为prev字典,key是模式,value初始化为1,表示第一行每种模式都只有1个。
- 然后就是从第2行开始遍历到最后一行。
- 在每一行的开始,先存一个字典curr,存储每种模式出现的次数。
- 然后重点来了!
- 遍历prev的key,从next[key]中取得全部可能的模式,更新curr[next[key]]。
- 注意这里更新的时候,需要每次累加prev[key]。
- 在每行结束的时候,将curr的内容存入prev。
- 程序最后将prev的value求和再取模,完事儿。
代码
class Solution:
def numOfWays(self, n: int) -> int:
pattern = [
'RGB', 'RBG', 'RGR',
'RBR', 'GBR', 'GRB',
'GRG', 'GBG', 'BRG',
'BGR', 'BRB', 'BGB'
]
# - construct transfer dict
# - to handle adjacent rows
next = {}
for p1 in pattern:
next[p1] = []
for p2 in pattern:
is_ok = True
for i in range(3):
if p1[i] == p2[i]:
is_ok = False
break
if is_ok:
next[p1].append(p2)
# - first row
prev = {p:1 for p in pattern}
# - from second row
for i in range(n-1):
# - d is temp dict for current row
curr = {p:0 for p in pattern}
# - accumulate
for k,v in prev.items():
for x in next[k]:
curr[x] += v
# - update previous row
prev = copy.copy(curr)
return sum(prev.values()) % (10**9 + 7)
爱生活,爱拉风