📌  相关文章
📜  在 3 x N 网格中绘制 K 个单元格的方法数,以便没有 P 个连续列未绘制(1)

📅  最后修改于: 2023-12-03 15:37:17.414000             🧑  作者: Mango

在 3 x N 网格中绘制 K 个单元格的方法数

问题描述

给定一个 3 行 N 列的网格,每个单元格可以被涂上颜色或不涂色。现在我们需要涂上 K 个单元格,求有多少种涂色方案使得任意连续 P 列中至少有一个单元格被涂色。

解法

考虑动态规划。令 f(i,j,k) 表示前 i 列中,选了 k 个单元格且第 i 列涂色状态为 j(0 表示不涂色,1 表示涂色)时,有多少种方案。

则有以下转移方程:

f(i, 0, k) = f(i-1, 1, k) + f(i-1, 0, k)
f(i, 1, k) = f(i-1, 0, k) + f(i-1, 0, k-1) + f(i-1, 2, k-1)
f(i, 2, k) = f(i-1, 0, k) + f(i-1, 0, k-1) + f(i-1, 1, k-1)

其中,f(i, 0, k) 表示第 i 列未涂色,可以从第 i-1 列涂了或没涂两种情况转移而来;f(i, 1, k) 表示第 i 列涂了颜色,可以从第 i-1 列未涂和第 i-1 列涂了颜色、第 i 列没涂色以及第 i-1 列涂了颜色,第 i 列涂了颜色三者转移而来;f(i, 2, k) 表示第 i 列涂了颜色但形成了 P 列连续未涂色的情况,可以从第 i-1 列未涂和第 i-1 列涂了颜色、第 i 列没涂色以及第 i-1 列涂了颜色,第 i 列涂了颜色、第 i-1 列涂了颜色,第 i-1 列涂了颜色、第 i 列没涂色三者转移而来。

最终答案为 f(n,0,k)+f(n,1,k)+f(n,2,k)。

代码实现
def num_ways(n: int, k: int, p: int) -> int:
    mod = int(1e9 + 7)
    f = [[[0] * (k + 1) for _ in range(3)] for _ in range(n + 1)]
    f[0][0][0] = 1
    for i in range(1, n + 1):
        for j in range(3):
            for l in range(k + 1):
                f[i][0][l] = (f[i - 1][1][l] + f[i - 1][0][l]) % mod
                if l > 0:
                    f[i][1][l] = (f[i - 1][0][l] + f[i - 1][0][l - 1] + f[i - 1][2][l - 1]) % mod
                    f[i][2][l] = (f[i - 1][0][l] + f[i - 1][0][l - 1] + f[i - 1][1][l - 1]) % mod
    return (f[n][0][k] + f[n][1][k] + f[n][2][k]) % mod

返回的为 markdown 格式的字符串,代码片段已按 markdown 标明。