1 条题解

  • 0
    @ 2026-4-2 15:59:34

    题目详解:C. 主教在哪里?

    题目理解

    我们有一个 8×88 \times 8 的棋盘,上面恰好放了一个主教(象)。主教可以攻击它所在位置以及沿四个对角线方向无限远的格子。主教不在棋盘边缘,即它的行 rr 和列 cc 满足 2r,c72 \le r, c \le 7

    输入给出了一个 8×88 \times 8 的棋盘,其中:

    • '#' 表示被主教攻击的格子
    • '.' 表示未被攻击的格子

    我们需要找出主教的位置 (r,c)(r, c)


    关键性质

    主教攻击的范围包括:

    1. 它自己的格子
    2. 它所在的左上一右下对角线(主对角线方向)上所有格子
    3. 它所在的右上一左下对角线(副对角线方向)上所有格子

    如果一个格子被主教攻击,它一定是:

    • 在主教所在的“十字对角线上”

    如何判断主教位置?

    主教在 (i,j)(i, j),那么:

    • (i,j)(i, j) 本身是 '#'
    • 它的四个“紧邻”对角线方向格子:
      • 左上:(i1,j1)(i-1, j-1)
      • 右上:(i1,j+1)(i-1, j+1)
      • 左下:(i+1,j1)(i+1, j-1)
      • 右下:(i+1,j+1)(i+1, j+1)

    重要观察
    如果主教不在边缘,这 55 个格子(中心 + 四个对角相邻格子)全都会被攻击,因此全为 '#'

    并且,由于主教是唯一的一个且不在边缘,整个棋盘上只有主教所在位置能满足“中心+四个对角相邻格子都是 '#'”这个条件


    为什么其他位置不行?

    • 如果一个格子是 '#' 但不是主教,它可能在主教的攻击对角线上,但它的四个对角相邻格子中,至少有一个不会被攻击(因为攻击是沿直线无限延伸,不拐弯)。
    • 特别地,中心点加上四个相邻对角线格子都是 '#' 的模式,唯一可能出现在主教的位置

    因此,我们只需遍历所有内部格子 (i,j)(i, j)2i,j72 \le i, j \le 7),检查:

    $$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] = \# $$

    如果成立,则 (i,j)(i, j) 就是主教的位置。


    复杂度分析

    • 每个测试用例只需检查最多 6×6=366 \times 6 = 36 个格子。
    • 每次检查是 O(1)O(1)
    • 总时间复杂度:O(t×36)=O(1)O(t \times 36) = O(1) 每个测试用例。

    示例验证

    以第一个测试用例为例(题目图示对应):

    .....#..
    #...#...
    .#.#....
    ..#.....
    .#.#....
    #...#...
    .....#..
    ......#.
    

    遍历内部格子,会发现 (4,3)(4,3) 满足上述条件,因此输出 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;
                }
            }
        }
    }
    
    • 注意数组下标从 11 开始,方便处理边界。
    • 只检查内部格子 2i,j72 \le i, j \le 7
    • 一旦找到符合条件的格子,立即输出并返回。

    其他方法

    另一种方法是求两条对角线的交点:

    • 找到所有 '#' 格子的左上-右下对角线的特征(rcr-c 为常数)
    • 找到所有 '#' 格子的右上-左下对角线的特征(r+cr+c 为常数)
    • 这两个常数的交点就是主教的位置。
      但实现比上面的模式匹配复杂一些。

    总结

    本题的关键是发现:
    主教不在边缘时,它和它四个紧邻对角线格子都一定是 '#',且只有主教满足这个 3×33 \times 3 的 X 形模式
    于是只需枚举内部格子检查该模式即可。

    • 1

    信息

    ID
    6239
    时间
    1000ms
    内存
    256MiB
    难度
    4
    标签
    递交数
    1
    已通过
    1
    上传者