1 条题解
-
0
问题分析
我们有一排 个格子,每个格子要么是空(
.),要么是阻塞(#)。
目标:让所有空格子最终都有水。
允许两种操作:- 在一个空单元格中放置水(操作 );
- 从一个已有水的单元格取出水,并放入任意另一个空单元格(操作 )。
此外,有一个自动填充规则:若某个空单元格 ()的左右邻居 和 都已经有水,则 会自动被水填满。
求最少需要执行多少次操作 。操作 次数不限。
关键观察
- 如果存在连续三个空单元格 ,那么我们可以先在 和 中放置水(两次操作 ),此时 自动填满。
- 然后,我们可以从 中取出水,放入任意其他空单元格(操作 )。由于 和 仍然有水, 会再次自动填满。
- 这意味着:只要有三连空,我们就能用 次操作 来“复制”出无限多的水,从而填满所有空单元格。
- 反之,如果没有三连空,那么自动填充规则永远不会被触发(因为任何自动填充都要求三个连续格子均为空,且两侧已经人为放水)。此时必须逐个在所有空单元格中执行操作 ,即操作 次数等于空单元格总数。
算法步骤
- 读入测试用例数 。
- 对每个测试用例:
- 读入 和字符串 。
- 初始化
empty_cnt = 0,has_three = false。 - 遍历 从 到 :
- 若 ,则
empty_cnt++; - 同时检查 且 且 ,若是则
has_three = true。
- 若 ,则
- 若
has_three == true,输出 ;否则输出empty_cnt。
时间复杂度 ,空间复杂度 (不计输入存储)。
正确性证明
情况一:存在三个连续空单元格
设三个连续空位置为 。- 在 和 中执行操作 (两次)。此时 因左右邻居有水而自动填满。
- 现在 都有水。
- 对于任意其他空单元格 :
- 使用操作 从 取出水,放入 。
- 由于 和 仍然有水, 会再次自动填满(因为它的左右邻居仍然有水)。
- 重复此过程,即可用无限次操作 将水扩散到所有空单元格。
因此只需要 次操作 。并且显然不可能少于 次(因为至少需要两个水源才能触发自动填充)。
情况二:不存在三个连续空单元格
自动填充规则永远不会生效(因为需要三个连续空位,且中间的空位必须左右都有水;但既然没有三个连续空位,任何水都无法通过自动规则传播到新的空单元格)。
因此,每个空单元格都必须通过操作 单独放置水。所以答案就是空单元格的数量。边界情况:
- :不可能有三个连续空位,因此答案直接是空单元格数。
- 没有空单元格:
empty_cnt = 0,输出 。
示例验证
以题目给出的测试用例为例:
3...
存在三个连续空 → 输出 。7##....#
子串"..."从下标 到 存在 → 输出 。7..#.#..
空位有 个,但没有三个连续空 → 输出 。4####
空位 → 输出 。10#...#..#.#
空位分布:下标 (共 个),但存在"..."吗?检查:- 下标 是
...→ 存在三连空 → 输出 。
- 下标 是
全部匹配输出。
复杂度分析
- 时间:每个测试用例扫描一次字符串,,轻松通过。
- 空间:仅使用常数个变量,。
总结
- 核心结论:如果存在三个连续的空单元格,答案为 ;否则答案为空单元格总数。
- 原因:三连空可以借助自动填充和水的移动(操作 )实现无限复制水,从而仅需最初的两个水源。
- 实现简单,只需扫描判断是否有
"..."子串,并统计'.'个数即可。
- 1
信息
- ID
- 6451
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者