1 条题解
-
0
题意回顾
有三个瓶子,容积分别为 ,初始橙汁量为 。
允许的操作:在两个瓶子间倒橙汁,只能倒空一个瓶子或倒满一个瓶子。
对于每个 ,求让某个瓶子恰好有 升橙汁的最少操作次数。数据范围:。
关键观察
1. 状态表示
系统的状态可以用三元组 表示,其中:
- = 第一个瓶子的橙汁量,
- = 第二个瓶子的橙汁量,
- = 第三个瓶子的橙汁量,
- 且 (总量守恒)
2. 操作类型
从状态 可以进行的操作:
- 从 瓶倒向 瓶:
- 倒空 :, (如果 )
- 倒满 :, (如果 )
- 实际倒的量是 ,其中剩余容量 =
3. 问题转化
我们需要找到从初始状态 出发,到达任意状态 的最少步数,其中 或 或 。
算法设计
BFS 搜索
由于状态空间有限,可以用 BFS 遍历所有可达状态。
状态数分析
- 有 种可能
- 有 种可能
- 由 确定
- 总状态数 ?太大!
需要优化状态表示。
状态优化
注意到 ,所以状态可由 唯一确定。
状态数 = ,仍然太大。但实际可达状态远少于理论值,因为 。
我们可以用哈希表或二维数组记录访问状态。
BFS 实现
数据结构
- 使用
dist[x][y]记录到达状态 的最少步数 - 初始化为 (未访问)
- 队列存储 状态
转移过程
对于当前状态 ,,尝试所有 6 种倒法:
- 1→2: 倒量 = ,新状态
- 1→3: 倒量 = ,新状态
- 2→1: 倒量 = ,新状态
- 2→3: 倒量 = ,新状态
- 3→1: 倒量 = ,新状态
- 3→2: 倒量 = ,新状态
答案记录
对于每个访问的状态 ,更新:
算法步骤
- 初始化 数组为
- 初始化 数组为
- ,将 加入队列
- BFS:
- 弹出队首 ,计算
- 更新
- 枚举 6 种倒法,生成新状态
- 如果新状态未访问,更新距离并入队
- 输出
复杂度分析
- 状态数:最多 ,但实际远少于
- 每个状态 6 个转移
- 使用哈希表:
- 可处理
样例验证
输入:,初始
BFS 过程:
- 初始状态 ,步数 0,更新
- 1→2: ,步数 1,更新
- 1→3: ,步数 1,更新 (已更优)
- 2→1: ,步数 1,更新
- 2→3: ,步数 1,更新
- 3→1: ,步数 1,更新
- 3→2: ,步数 1,更新
- 继续 BFS 找到更多状态...
最终得到输出:
1 0 1 0 1 1 0 1 2 1
总结
本题的核心解法是状态空间 BFS:
- 用 表示状态, 由总量确定
- BFS 遍历所有可达状态
- 记录每个 值的最少步数
- 输出 到 的答案
通过 BFS 可以找到所有可达状态的最短路径,解决这个倒水问题。
- 1
信息
- ID
- 4549
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 4
- 已通过
- 1
- 上传者