📜  门|门 CS 1997 |第 75 题(1)

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

题目介绍:门|门 CS 1997 |第 75 题

这是一道经典的动态规划题目,题目描述如下:

有 n 个门排成一排,每个门处设有一个传送门,可以传送至当前位置加上 k 或减去 k 的位置(其中 k 为一个定值)。每个门上有一个开关,初始时所有门都关闭。现在进行 m 次操作,每次操作为将一个区间中的所有门的开关状态取反(即开关开着的变为关,关着的变为开)。求在进行完所有操作后,第一个门的开关状态是否为开。

解题思路

这道题目需要使用动态规划来解决。我们定义 $dp[i][j]$ 表示第 $i$ 个门状态为 $j$ 的方案数。其中 $j=0$ 表示门关闭,$j=1$ 表示门打开。

那么对于当前门的状态,可以分为两种情况:

  1. 当前门没有被操作过,即当前门不属于被操作区间。此时当前门的状态不会受到影响,因此当前门状态的方案数就等于上一门的状态,即 $dp[i-1][j]$。

  2. 当前门被操作过,即当前门属于被操作区间。此时当前门的状态会被取反,因此当前门状态的方案数就等于上一门状态与上上门状态之和,即 $dp[i-1][j] + dp[i-1][1-j]$。

时间复杂度为 $O(n^2)$,空间复杂度为 $O(n)$。

代码实现

def solve(n, m, k, l, r):
    # 初始化
    dp = [[0] * 2 for _ in range(n+1)]
    dp[0][0] = 1  # 第 0 个门为关闭状态的方案数为 1

    # 动态规划
    for i in range(1, n+1):
        for j in range(2):
            # 情况1:当前门不属于被操作区间
            if l <= i <= r:
                dp[i][j] = dp[i-1][j] + dp[i-1][1-j]
            # 情况2:当前门属于被操作区间
            else:
                pre = i - k if j == 1 else i + k
                if 1 <= pre <= n:
                    dp[i][j] = dp[i-1][j] + dp[i-1][1-j] - dp[pre-1][1-j]
                else:
                    dp[i][j] = dp[i-1][j] + dp[i-1][1-j]

        # 取反
        if l <= i <= r:
            dp[i][0], dp[i][1] = dp[i][1], dp[i][0]

    # 返回第一个门是否为开状态
    return dp[1][m % 2]

以上就是本题的解题思路和代码实现。