📌  相关文章
📜  绘制3 x N网格中的K单元以使所有P连续列不被绘制的方式的数量(1)

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

题目描述

给定一个 $3×N$ 的网格和整数 $K$ 和 $P$,求绘制 $K$ 个长度为 $3$ 的不同列,使得每连续的 $P$ 个列中都至少存在一个列不被绘制的方法数量。

解法分析

这道题可以使用动态规划来解决。

首先,我们定义 $dp[i][j][k]$ 表示绘制到第 $i$ 列,其中已经绘制了 $j$ 个长度为 $3$ 的不同列,且最后一个绘制的是第 $k$ 列的方案数。我们可以利用状态转移方程来求解:

$$ dp[i][j][k] = \sum_{c=1}^{3} dp[i-1][j-(c==k)][c] $$

意思是:第 $i$ 列有三种可能的绘制方法,即和第 $k$ 列的绘制方法不同,和第 $k$ 列的绘制方法相同但是与上一列的绘制方法不同,和上一列的绘制方法相同。我们只需要枚举 $c$,然后将所以可能的情况相加起来就可以了。

下一步是判断限制条件:每连续的 $P$ 个列中必须有至少一列没有被绘制。在计算 $dp[i][j][k]$ 的时候,我们需要同时记录第 $i-P$ 列到第 $i-1$ 列中被绘制的列的编号 $l$,如果 $j-l<P$,且第 $k$ 列恰好等于其中一列的编号,那么这个状态就不能被转移。

具体来说,可以再开一个一维数组 $last$,其中 $last[s]$ 表示编号为 $s$ 的列在 $(i-P,i-1)$ 区间内最后一次被绘制的位置。如果这个列在区间内没有被绘制过,令 $last[s]=-1$。

我们只需要在状态转移方程中加入判断即可:

$$ dp[i][j][k] = \sum_{c=1}^{3} [k≠c] \cdot dp[i-1][j-(c==k)][c] \cdot [l < i-P \textrm{ 或 } j-l<P \textrm{ 或 } c≠ k] $$

代码实现
def count_ways(n, k, p):
    dp = [[[0] * 4 for _ in range(k+1)] for _ in range(n+1)]
    last = [-1] * 4
    
    dp[0][0][0] = 1
    for i in range(1, n+1):
        for j in range(k+1):
            for k in range(1, 4):
                s = j-(k==last[k])
                if s>=0 and s<p:
                    dp[i][j][k] = 0
                else:
                    dp[i][j][k] = sum(dp[i-1][s+(c==k)][c] for c in range(1, 4) if j-(c==last[c])>=p)
                    dp[i][j][k] %= 998244353
            last[k] = i if dp[i][j][k]>0 else last[k]
    
    ans = sum(dp[n][k][i] for i in range(1, 4))
    return ans % 998244353

其中 nkp 分别表示网格的列数、需要绘制多少列、每连续多少列必须有一列没有被绘制,函数返回的结果即为所有符合要求的绘制方案数量。此外,这段代码的时间复杂度为 $O(nkp)$,空间复杂度为 $O(nk)$。