📅  最后修改于: 2023-12-03 15:37:17.414000             🧑  作者: Mango
给定一个 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 标明。