BISHI82 没挡住洪水¶
简单通过率 24.99%python3样例通过牛客 AC广度优先搜索(BFS)
讲解章节:BFS 广度优先搜索
一句话
N*N 网格,问有多少个 '#' 四连通区域会在一天后被「完全」淹没。
解题思路¶
这题考什么¶
连通块搜索 + 读题。洪水上涨的规则是:
注意这是一次性、同时发生的一轮,不是反复扩散到收敛。 所以一个区域被「完全」淹没 <=> 区域里的每一个格子都至少有一个 四方向邻居是 '.'。于是只要在遍历连通块时对每个格子检查一遍邻居即可。
常见错解:以为洪水会一轮轮往里渗,于是判定成「区域全被淹」总是成立; 或者只判「区域边界挨着水」就算完全淹没——那只淹掉了外壳, 厚度 >= 3 的实心块中心是淹不到的。
数据规模与复杂度¶
N <= 1000 -> 1e6 格。每格入队一次、看 4 个邻居,O(N^2)。
Python 的坑¶
- 队列用 collections.deque,1e6 规模下 list.pop(0) 必然退化;
- 网格压一维 + 四周补 '.' 哨兵。题面已保证四条边界全是被淹区域, 补 '.' 与题意一致,同时消除了越界判断;
- 入队即标记(把 '#' 改写成已访问标记 'x'),避免重复入队;
- 判定「该格是否会被淹」时要用原始地图的 '.', 所以已访问标记不能也写成 '.',否则会把同区域的兄弟格误判成水。 这里用第三种字符 'x' 区分。
其它坑¶
- 洪水只涨一轮。写成「反复扩散直到不再变化」的话,任何区域最终都会被 淹完,答案会变成区域总数;
- 「完全淹没」要求区域里每一格都挨着水,因此 all_flooded 必须在整块搜完之后 才下结论:中途遇到一个不挨水的格子就置 False,但不能提前退出, 否则这块区域剩下的格子不会被标记,会被当成新区域重复计数;
- 补的一圈哨兵是 '.',与题面「边界四条边全部已被淹没」一致,所以贴边的 陆地会被哨兵正确判成「挨着水」,不是为了省判断而人为放水;
- 一格都没有陆地时答案是 0(样例的 N=1 全是 '.' 就是这种情况)。
参考实现¶
[:octicons-arrow-left-16: BISHI81](BISHI81.md) [BISHI83 :octicons-arrow-right-16:](BISHI83.md)