ATCODER ABC 450 C题解如何用提问?

摘要:ATCODER ABC 450 C [Atcoder ABC 450 C](C - Puddles) 题意概述: 二维字符数组中,找到联通的.的组合并且处在内部,没有点在最外层 难点: 因为想不到或者不知道这道题的算法是什么,我想枚举模拟,
ATCODER ABC 450 C [Atcoder ABC 450 C](C - Puddles) 题意概述: 二维字符数组中,找到联通的.的组合并且处在内部,没有点在最外层 难点: 因为想不到或者不知道这道题的算法是什么,我想枚举模拟,但是在枚举模拟的过程中,我发现,我模拟从一个串的开始到串的末尾,这个过程很难模拟出来,所以暴力做法也写不出来,最后,看官方题解以及问ai,才知道这道题要用BFS(广度优先搜索) BFS: 为什么要用BFS 这道题是一个连通块问题,等效于要求我们统计“不漏水”的水坑,bfs的核心思想就是从一个点开始,向四周扩散,所以这道题的要求很契合bfs 具体思路 用两个数组表示平移到上下左右 用一个二维bool数组表示该格子是否被扫描过 循环每个字符 假如一个字符没被扫描过,并且是.,以它为头建造一个队列(存储pair),记住存入队列就马上标记(原因见下文). 设定一个bool数来表示连通串是否有点在边界 bfs寻找:首先判断当前的坐标是否在边界内,即使在边界,还是要把邻居找完,不然之后还是循环到邻居还是要再找,可能导致重复找邻居,效率低下.找邻居(注意判断坐标边界条件,将邻居push进队列,进队列就标记) 进队列就标记的原因: 如下例子所示: 1. 2×2 地图的“包抄”过程 假设四个点全是水坑 .: A \((0,0)\) —— 起点 B \((1,0)\) —— A 的下方邻居 C \((0,1)\) —— A 的右方邻居 D \((1,1)\) —— B 的右方邻居,同时也是 C 的下方邻居 第一步:处理 A \((0,0)\) A 看向四周,发现了 B \((1,0)\) 和 C \((0,1)\)。 A 把 B 和 C 都丢进队列排队。 此时队列:[B, C]。注意:此时 B 和 C 还没出队,所以还没被贴上 cg=1 的标签。 第二步:轮到 B \((1,0)\) 出队 B 贴上标签 cg[1][0]=1。 B 看向它的邻居,发现了 D \((1,1)\)。 B 发现 D 还没贴标签,于是把 D 丢进队列。 此时队列:[C, D]。注意:此时 D 已经在排队了,但因为还没出队,它的标签 cg[1][1] 依然是 0。 第三步:轮到 C \((0,1)\) 出队 C 贴上标签 cg[0][1]=1。 C 看向它的邻居,也发现了 D \((1,1)\)! 关键冲突点:C 检查 cg[1][1],发现竟然是 0(因为 D 还在后面排队呢,没轮到它贴标签)。 C 以为 D 是个没人管的“新发现”,于是又把 D 丢进了一次队列。 最终队列:[D, D]。 2. 为什么这很可怕? 虽然 \((1,0)\) 和 \((0,1)\) 互不相识,但它们像两个不沟通的部门,同时看中了同一个员工 D。 在一个大迷宫里,任何一个空格子(比如 \((x, y)\))通常都有 4 个邻居。 这意味着,如果你不在入队那一刻就贴上标签,这个格子可能会被它的上下左右邻居每人举报一次。 在你的 while 循环里,原本这个格子只需要处理 1 次,现在却要处理 4 次。而这 4 次处理又会引发出更多的重复……这种冗余会像病毒一样在你的队列里疯狂繁殖。
阅读全文