1 条题解

  • 0
    @ 2025-11-12 21:15:53

    题目理解

    我们有一个 H×WH \times W 的网格,需要在其中放置帐篷。每个帐篷有四个可能的朝向(东、南、西、北),但需要满足严格的朝向约束条件:

    • 列约束:同一列中,上方的帐篷必须朝南,下方的帐篷必须朝北
    • 行约束:同一行中,左侧的帐篷必须朝东,右侧的帐篷必须朝西

    我们需要计算至少放置一个帐篷的所有合法方案数,对 109+710^9+7 取模。

    问题分析

    1. 约束条件解读

    约束条件实际上限制了:

    • 同一列中最多只能有一列连续的帐篷
    • 同一行中最多只能有一行连续的帐篷
    • 帐篷的朝向由其在行/列中的相对位置完全确定

    2. 问题转化

    这实际上是一个组合计数问题,我们需要计算在满足上述约束条件下的所有帐篷放置方案。

    算法思路

    1. 动态规划状态设计

    代码使用二维DP:dp[i][j] 表示考虑了前 i 行,当前行已放置帐篷的列集合大小为 j 时的方案数。

    • i:当前处理到的行数(从下往上处理)
    • j:当前行中已放置帐篷的列数

    2. 状态转移方程

    核心转移在代码中体现为:

    dp[i - 1][j - 1] = (dp[i][j - 1]
                        + dp[i][j + 1] * (组合数项)
                        + dp[i][j]     * (系数项)
                        + dp[i + 1][j] * (系数项)) % MOD;
    

    具体分析四种转移:

    1. dp[i][j - 1]:减少一列帐篷
    2. dp[i][j + 1] * C(j+1, 2):选择两列合并(组合数)
    3. dp[i][j] * (4j):在当前列集合基础上扩展(4种朝向选择)
    4. dp[i + 1][j] * (i * j):与下一行的交互

    3. 初始化与答案计算

    // 初始化:最后一行所有列状态为1
    for (i = 0; i <= n; ++i) {
        dp[i][m] = 1;
    }
    
    // 从下往上递推
    for (i = n; i; --i) {
        for (j = m; j; --j) {
            // 状态转移
        }
    }
    
    // 统计答案:所有第一行的状态
    for (i = 0; i < m; ++i) {
        ans += dp[0][i];
    }
    

    关键算法细节

    1. 处理顺序

    采用从下往上、从右往左的递推顺序,确保在计算每个状态时,所需的前置状态都已计算完成。

    2. 组合计数技巧

    • 使用 (j + 1) * j >> 1 计算组合数 C(j+1,2)C(j+1, 2)
    • 使用 j << 2 表示 4j4j,对应4种朝向选择
    • 使用 i * j 表示行与列之间的交互方案数

    3. 模运算处理

    由于结果可能很大,所有运算都对 109+710^9+7 取模:

    dp[i - 1][j - 1] = (...各种项...) % 1000000007;
    

    复杂度分析

    • 状态数O(H×W)O(H \times W)
    • 转移复杂度O(1)O(1) 每个状态
    • 总复杂度O(H×W)O(H \times W)
    • 空间复杂度O(H×W)O(H \times W)

    对于 H,W3000H, W \leq 3000,复杂度为 9×1069 \times 10^6,是可接受的。

    算法优化

    1. 滚动数组:可以优化空间复杂度到 O(W)O(W)
    2. 寄存器变量:代码中使用 register 关键字优化访问速度
    3. 位运算:使用移位代替除法提高效率

    算法标签

    • 动态规划:核心算法框架
    • 组合数学:方案数计算涉及组合计数
    • 计数DP:专门解决计数问题的动态规划
    • 模运算:大数取模处理

    总结

    这道题通过巧妙的动态规划状态设计,将复杂的朝向约束条件转化为可计算的状态转移。算法的核心在于:

    1. 状态定义dp[i][j] 精确捕捉了行和列的约束关系
    2. 转移方程:四种情况完整覆盖了所有可能的帐篷放置方式
    3. 边界处理:合理的初始化和答案统计
    4. 优化技巧:寄存器变量、位运算等提升效率

    该解法充分利用了动态规划在组合计数问题中的优势,是计数类DP的典型应用。

    • 1

    信息

    ID
    5311
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者