1 条题解
-
0
题目详解:C. 主教在哪里?
题目理解
我们有一个 的棋盘,上面恰好放了一个主教(象)。主教可以攻击它所在位置以及沿四个对角线方向无限远的格子。主教不在棋盘边缘,即它的行 和列 满足 。
输入给出了一个 的棋盘,其中:
'#'表示被主教攻击的格子'.'表示未被攻击的格子
我们需要找出主教的位置 。
关键性质
主教攻击的范围包括:
- 它自己的格子
- 它所在的左上一右下对角线(主对角线方向)上所有格子
- 它所在的右上一左下对角线(副对角线方向)上所有格子
如果一个格子被主教攻击,它一定是:
- 在主教所在的“十字对角线上”
如何判断主教位置?
主教在 ,那么:
- 本身是
'#' - 它的四个“紧邻”对角线方向格子:
- 左上:
- 右上:
- 左下:
- 右下:
重要观察:
如果主教不在边缘,这 个格子(中心 + 四个对角相邻格子)全都会被攻击,因此全为'#'。并且,由于主教是唯一的一个且不在边缘,整个棋盘上只有主教所在位置能满足“中心+四个对角相邻格子都是
'#'”这个条件。
为什么其他位置不行?
- 如果一个格子是
'#'但不是主教,它可能在主教的攻击对角线上,但它的四个对角相邻格子中,至少有一个不会被攻击(因为攻击是沿直线无限延伸,不拐弯)。 - 特别地,中心点加上四个相邻对角线格子都是
'#'的模式,唯一可能出现在主教的位置。
因此,我们只需遍历所有内部格子 (),检查:
$$g[i][j] = \# \quad \text{且} \quad g[i-1][j-1] = \# \quad \text{且} \quad g[i-1][j+1] = \# \quad \text{且} \quad g[i+1][j-1] = \# \quad \text{且} \quad g[i+1][j+1] = \# $$如果成立,则 就是主教的位置。
复杂度分析
- 每个测试用例只需检查最多 个格子。
- 每次检查是 。
- 总时间复杂度: 每个测试用例。
示例验证
以第一个测试用例为例(题目图示对应):
.....#.. #...#... .#.#.... ..#..... .#.#.... #...#... .....#.. ......#.遍历内部格子,会发现 满足上述条件,因此输出
4 3。
代码实现(标程解读)
void solve() { char g[9][9]; for (int i = 1; i <= 8; i++) { for (int j = 1; j <= 8; j++) { cin >> g[i][j]; } } for (int i = 2; i <= 7; i++) { for (int j = 2; j <= 7; j++) { if (g[i][j] == '#' && g[i-1][j-1] == '#' && g[i-1][j+1] == '#' && g[i+1][j-1] == '#' && g[i+1][j+1] == '#') { cout << i << ' ' << j << '\n'; return; } } } }- 注意数组下标从 开始,方便处理边界。
- 只检查内部格子 。
- 一旦找到符合条件的格子,立即输出并返回。
其他方法
另一种方法是求两条对角线的交点:
- 找到所有
'#'格子的左上-右下对角线的特征( 为常数) - 找到所有
'#'格子的右上-左下对角线的特征( 为常数) - 这两个常数的交点就是主教的位置。
但实现比上面的模式匹配复杂一些。
总结
本题的关键是发现:
主教不在边缘时,它和它四个紧邻对角线格子都一定是'#',且只有主教满足这个 的 X 形模式。
于是只需枚举内部格子检查该模式即可。
- 1
信息
- ID
- 6239
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 4
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者