通过率 60% · 提交 372 · 通过 225
小慕最近在学习围棋,他发现围棋棋盘由纵横各19条线垂直相交组成,棋盘上一共19x19=361个交点,对弈双方一方执白棋,一方执黑棋,落子时只能将棋子置于交点上。 “”是围棋中很重要的一个概念,某个棋子有几口气,是指其上下左右方向四个相邻的交叉点中,有几个交叉点没有棋子,由此可知: 1、在棋盘的边缘上的棋子最多有3口气(黑1),在棋盘角点的棋子最多有2口气(黑2),其它情况最多有4口气(白1) 2、如果多个相同颜色的棋子连在一起,那么这些棋子会共享它们的气,即这些棋子共同的气的总数,等于这些棋子上下左右方向所有相邻的交叉点中,没有棋子的交叉点的总数(注意:这些棋子本身占据的交叉点不算在内,并且这些棋子共同占据的交叉点相邻的交叉点中,如果有相同颜色的棋子,那么这些交叉点也不会计入气中,因为它们是棋子的一部分,而不是气)。下图中的黑棋三子连在一起,共同的气共有7口(图中标记为X的位置) 3、如果某块棋子(可能是单个或多个棋子)的气数为0,那么这些棋子就处于无气状态,应当立即被从棋盘上提走。提走棋子后,可能会使得其它棋子获得新的气。 现在,小慕遇到了一个问题:给定一个围棋棋盘上若干棋子的分布,他想知道棋盘上所有棋子各自的气数分别是多少。注意,这里的棋子气数是针对每一个单独的棋子而言的,即每个棋子所在连通块的气数,就是该棋子自身的气数。
这类题属于华为 OD 机考真题方向中「100分 / 2024D」方向的高频题型,通常考察对「100分 / 2024D」的建模能力与边界条件处理。掌握本题的解题思路后,可举一反三应对同类真题方向,稳步提升机考通过率。
提示:带虚线的词点一下有通俗解释。
输入包括两行数据,如:
0 5 8 9 9 10
5 0 9 9 9 8
1、每行数据以空格分隔,数据个数是2的整数倍,每两个数是一组,代表棋子在棋盘上的坐标
2、坐标的原点在棋盘左上角点,第一个值是行号,范围从0到18;第二个值是列号,范围从0到18
3、举例说明:第一行数据表示三个坐标(0, 5)、(8, 9)、(9, 10)
4、第一行表示黑棋的坐标,第二行表示白棋的坐标。
5、题目保证输入两行数据,无空行且每行按前文要求是偶数个,每个坐标不会超出棋盘范围。
8 7 两个数字以空格分隔,第一个数代表黑棋的气数,第二个数代表白棋的气数。
示例 1
输入示例
0 5 8 9 9 10 5 0 9 9 9 8
输出示例
8 7
时间限制 1000 ms · 内存限制 128 MB
本平台为独立第三方培训机构,与华为技术有限公司无任何关联;课程的服务内容与权益以购买协议为准,学习效果因个人情况而异。「华为 OD」「华为可信」等仅为对岗位与考试方向的客观描述,相关商标归各自权利人所有。
考虑正向的思路,即从棋子位置出发,计算每一个棋子上下左右的气的个数。以黑棋为例(白棋完全类似)。
由于如例子所示的多个同色棋子共有气的情况的出现,假设某一个空位 (ni, nj) 是黑棋的共有气,为了不被重复计算,我们需要将 (ni, nj) 存入一个哈希集合 black_qi_set 中。那么,当下一次考虑到同一个空位 (ni, nj) 时,就不会多次储存了。
1. 构建偏移数组 D = [(0, 1), (1, 0), (0, -1), (-1, 0)],构建哈希集合 qi_set。 2. 遍历所有黑棋 (i, j)。 3. 对于每一个黑棋的位置 (i, j),遍历偏移量 (di, dj),计算近邻点 (ni, nj)。 4. 若 (ni, nj) 没有越界,且是空位(即既不为黑棋也不为白棋),则将 (ni, nj) 加入哈希集合 qi_set 中。 5. 所有遍历结束后,返回 len(qi_set) 即为黑棋的气的数量。
由于白棋和黑棋计算气的过程是相似的,可以构造一个函数 cal_qi_num() 来计算气的个数:
除了正向思路以外,本题还存在逆向的思路,即从所有空位出发,查看这个空位的周围是否存在黑棋或白棋。这种做法同样需要用到哈希集合来完成,感兴趣的同学可以尝试。
类似于 【模拟】2025C-统计监控中 的做法。
复杂度分析
设黑棋有 B 颗、白棋有 W 颗,棋子总数记为 S = B + W。
cal_qi_num 函数对传入颜色的每颗棋子只做固定的 4 次近邻检查,每次检查包含两次哈希集合查询(近邻点是否为同色棋子、是否为异色棋子)和至多一次插入,均摊 O(1)。所以统计黑棋的气是 O(4B),统计白棋的气是 O(4W),两次调用合计 O(S),时间与棋子总数成正比。由于棋盘固定为 19x19,S 最多 361,实际运算量是很小的常数级别。
空间方面,set_black、set_white 存放全部棋子坐标,set_qi 最多存下所有空交叉点,整体 O(S) 且受 361 个交叉点封顶。
哈希集合在这里有两个作用:一是让“某个交叉点上有没有棋子”的判断变成平均 O(1) 的查询,不必构建整张棋盘的二维数组也能快速判定;二是对多颗同色棋子共享的气自动去重,保证同一口共有气只被计数一次,这正是正文强调用集合而不用计数器累加的原因。
登录后可查看你在本题的历史提交,以及每次的各用例通过情况。
© 2026 广州慕课网络科技有限公司 · 吴师兄学算法官网 版权所有