算法
看到数据范围很小, 考虑状压 \(\rm{dp}\)
我们考虑从左上往右下推答案, 那么显然的, 我们只需要考虑向上向左方向的冲突情况, 而无需考虑向下向右的
考虑轮廓线 \(\rm{dp}\) , 虽然不太标准就是了
实际上对于这样的情况, 我们考虑枚举绿色部分是否选择, 然后对状态进行转移
分类讨论
当绿色部分不选择时
这个时候只要之前的状态不冲突, 即状态合法, 都可以转移
具体的, 对于图中的这种情况, 我们可以转移到
那么状态怎么变化?
具体的, 对于两行, 都只需要把修改那一位的位置更新, 其他的不变即可
当绿色部分选择时
这个时候我们需要确保无冲突情况和无障碍物, 我们只需要确保上方两块和左侧两块上没有炮兵部队即可
这样做, 时间复杂度是 \(\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}\)
滚动一下即可
实现
框架
- 对于每一个位置, 枚举产生符合要求的状态
- 转移即可
代码
还在调, 后补
总结
状压常见优化
- 提前把有效状态筛出来, 防止无效的转移
逐一讨论的完整性
状态压缩这样的问题, 一定要想办法简化代码
标签:状态,考虑,位置,炮兵阵地,即可,NOI2001,line,转移 From: https://www.cnblogs.com/YzaCsp/p/18592216