Leetcode 1411:给Nx3网格图涂色的方案数(超详细的解法!!!)

本文探讨了一种高效算法,用于计算n x 3网格图中使用红、黄、绿三种颜色进行染色的方案总数,确保相邻格子颜色不同。通过动态规划方法,将问题简化为两种基本模式的迭代计算,最终得出对10^9+7取余后的结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

你有一个 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

解题思路

首先比较容易想到的思路就是记忆化加递归,每次枚举每个位置的颜色使其和上边和左边的颜色不同即可。当枚举到最后一行最后一列的时候,返回当前位置可选的颜色数目即可。

from functools import lru_cache
class Solution:
    def numOfWays(self, n: int) -> int:
        mod = 10 ** 9 + 7
        s1 = set([1, 2, 3])
        
        @lru_cache(None)
        def dfs(x, y, pre, cur):
            s2 = [pre[y]]
            if y: s2.append(cur[y - 1])
            t = list(s1 - set(s2)) # 当前位置可以使用的颜色
            
            if y == 2:
                if x == n - 1: return len(t)
                res = 0
                for i in t:
                    t_cur = list(cur)
                    t_cur[y] = i
                    res = (res + dfs(x + 1, 0, tuple(t_cur), (0, 0, 0))) % mod
                return res

            res = 0
            for i in t:
                t_cur = list(cur)
                t_cur[y] = i
                res = (res + dfs(x, y + 1, pre, tuple(t_cur))) % mod
            return res

        return dfs(0, 0, (0, 0, 0), (0, 0, 0))

这个问题还有一个非常简洁的思路,对于每一行的颜色,考虑其分布规律可以分成两种形式:1)两边的颜色相同aba。2)三个位置颜色都不相同abc

那么,第一行按照第一种形式可以是:121131212232313323。按照第二种形式的话可以有:123132213231312321

接着思考第二层的摆放,如果第一层是121的话,那么第二层可以是212213232312313,对于其他第一种形式的类似,都会有3aba2abc情况。如果第一层是第二种形式的话,都会有2aba2abc的情况。可以定义函数 f a b a ( n ) f_{aba}(n) faba(n)表示第naba这种摆放方式的数目,可以定义 f a b c ( n ) f_{abc}(n) fabc(n)表示第nabc这种摆放方式的数目,那么:

  • f a b a ( n ) = 3 ∗ f a b a ( n − 1 ) + 2 ∗ f a b c ( n − 1 ) f_{aba}(n)=3*f_{aba}(n-1)+2*f_{abc}(n-1) faba(n)=3faba(n1)+2fabc(n1)
  • f a b c ( n ) = 2 ∗ f a b a ( n − 1 ) + 2 ∗ f a b c ( n − 1 ) f_{abc}(n)=2*f_{aba}(n-1)+2*f_{abc}(n-1) fabc(n)=2faba(n1)+2fabc(n1)

最后的结果显然就是 f a b c ( n ) + f a b a ( n ) f_{abc}(n)+f_{aba}(n) fabc(n)+faba(n)

class Solution:
    def numOfWays(self, n: int) -> int:
        aba, abc, mod = 6, 6, 10**9 + 7
        for i in range(n - 1):
            aba, abc = aba * 3 + abc * 2, aba * 2 + abc * 2
        return (aba + abc) % mod

reference:

https://leetcode.com/problems/number-of-ways-to-paint-n-3-grid/discuss/574923/JavaC%2B%2BPython-DP-O(1)-Space

我将该问题的其他语言版本添加到了我的GitHub Leetcode

如有问题,希望大家指出!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值