1 条题解
-
0
问题分析
我们有:
- 个错误()
- 个补丁,每个补丁有:
- 适用条件:(必须有的错误),(必须没有的错误)
- 效果:(修复的错误),(引入的错误)
- 耗时
目标:从全错状态 到无错状态 的最短时间。
关键思路
状态表示
由于 ,可以用二进制状态压缩:
- 状态 是一个 位二进制数
- 第 位为 表示存在第 个错误,为 表示已修复
状态转移
对于每个状态 ,尝试应用每个补丁 :
检查补丁 是否可用:
- 中所有错误必须在 中出现:
(S & B1_mask) == B1_mask - 中所有错误必须在 中不出现:
(S & B2_mask) == 0
应用补丁 后的新状态:
- 修复 中的错误:
- 加入 中的错误:
边权:补丁 的耗时
算法选择
这实际上是一个带权有向图最短路问题:
- 节点:所有 个可能的状态
- 边:如果状态 能通过补丁 到达状态 ,则有一条权值为 的边
使用 Dijkstra 算法 求从全错状态到无错状态的最短路径。
样例验证
输入:
3 3 1 000 00- 1 00- 0-+ 2 0-- -++,初始状态 ,目标状态
补丁分析(错误编号从 0 开始,字符串从左到右对应错误 0,1,2):
补丁1:耗时 1
- 条件:
000→ (无条件可用) - 效果:
00-→ 修复错误2 - 转移:
补丁2:耗时 1
- 条件:
00-→ (错误2必须不存在) - 效果:
0-+→ 修复错误1,引入错误2 - 转移:
补丁3:耗时 2
- 条件:
0--→ (错误1,2必须不存在) - 效果:
-++→ 修复错误0,引入错误1,2 - 转移:
最短路过程:
- (用补丁1修复错误2)
- (用补丁2修复错误1,引入错误2)
- (用补丁1修复错误2)
- (用补丁3修复错误0,引入错误1,2)
- (用补丁1修复错误2)
- (用补丁2修复错误1,引入错误2)
- (用补丁1修复错误2)
总耗时:
算法步骤
- 读入
- 对每个补丁 ,预处理四个掩码:
- :条件中必须存在的错误
- :条件中必须不存在的错误
- :修复的错误
- :引入的错误
- 初始化距离数组 ,(全错状态)
- 使用优先队列运行 Dijkstra:
- 对于当前状态 ,尝试每个补丁
- 检查是否满足条件
- 计算新状态 和新距离
- 如果更优则更新
- 输出 ,如果为 则输出
复杂度分析
- 状态数:
- 每个状态尝试 个补丁
- 总复杂度: 级别
- 在 时稍大但可接受(实际很多状态不可达)
总结
这道题通过状态压缩表示错误集合,将补丁应用建模为状态转移,用最短路算法求解最小耗时,是状态空间搜索的经典例题。虽然归类在网络流 24 题中,但实际解法展示了不同算法在解决实际问题时的灵活性。
- 1
信息
- ID
- 3947
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者