Loading

[NOI2001] 炮兵阵地

算法

看到数据范围很小, 考虑状压 \(\rm{dp}\)

我们考虑从左上往右下推答案, 那么显然的, 我们只需要考虑向上向左方向的冲突情况, 而无需考虑向下向右的

考虑轮廓线 \(\rm{dp}\) , 虽然不太标准就是了

k5qh2z51.png

实际上对于这样的情况, 我们考虑枚举绿色部分是否选择, 然后对状态进行转移

分类讨论

当绿色部分不选择时

这个时候只要之前的状态不冲突, 即状态合法, 都可以转移

具体的, 对于图中的这种情况, 我们可以转移到
g5sgdl19.png

那么状态怎么变化?
具体的, 对于两行, 都只需要把修改那一位的位置更新, 其他的不变即可

当绿色部分选择时

这个时候我们需要确保无冲突情况和无障碍物, 我们只需要确保上方两块和左侧两块上没有炮兵部队即可

这样做, 时间复杂度是 \(\mathcal{O} (nm 2 ^ {2m})\) , 显然是过不去的

考虑到很多状态根本不合法, 根本跑不满, 我们提前判断每种状态的正确性即可预处理出合法状态, 这样可以通过本题

状态转移

根据以上的讨论, 我们尝试写出转移式子

\(f_{i, j, line_1, line_2}\) 表示考虑 \((i, j)\) , 当前两行的状态为 \(line_1, line_2\) 时最多放置的部队数量

  • 不选择当前点
    更新 \(line_1\) 的第 \(j\) 位为 \(line_2\) 的第 \(j\) 位, \(line_2\) 的第 \(j\) 位更新为 \(0\)

  • 选择当前点
    首先判断地形, 然后判断 \(line_2\)\(j - 1, j - 2\) 位置, 判断 \(line_1\)\(j\) 位置和 \(line_2\)\(j\) 位置是否都不为 \(1\) , 转移

初始化 \(f_{0, 0, 0, 0} = 0\) , 最后的答案即为 \(\max f_{n - 1, m - 1, line_1, line_2}\)

滚动一下即可

实现

框架

  • 对于每一个位置, 枚举产生符合要求的状态
  • 转移即可

代码

还在调, 后补

总结

状压常见优化

  • 提前把有效状态筛出来, 防止无效的转移

逐一讨论的完整性

状态压缩这样的问题, 一定要想办法简化代码

posted @ 2024-12-07 15:31  Yorg  阅读(80)  评论(0)    收藏  举报