1 条题解

  • 0
    @ 2026-6-19 10:30:47

    📝 题目大意

    有一个 H×W 的网格(初始全白),网格边界是循环的(环面)。从 (1,1) 面朝上方出发,重复 N 次:若当前格子为白色则涂黑并顺时针转 90° 前进一格,若为黑色则涂白并逆时针转 90° 前进一格。输出最终网格状态。

    💡 解题思路

    1. 题目分析:这是一道经典的"兰顿蚂蚁"(Langton's Ant)模拟题。约束条件 H, W ≤ 100,N ≤ 1000,数据范围很小,直接模拟即可,无需优化。

    2. 算法推导

      • grid[H][W] 存储网格,初始全为 '.'(白色)。
      • 位置 (x, y) 初始为 (0, 0),对应题目中的 (1, 1)
      • 方向数组 dx[4] = {-1, 0, 1, 0}dy[4] = {0, 1, 0, -1},分别对应上、右、下、左四个方向。dir = 0 表示初始面朝上方。
      • 顺时针旋转 90°:dir = (dir + 1) % 4(相当于上→右→下→左→上)。
      • 逆时针旋转 90°:dir = (dir + 3) % 4(等价于 (dir - 1 + 4) % 4,即上→左→下→右→上)。
      • 环面移动:x = (x + dx[dir] + H) % Hy = (y + dy[dir] + W) % W,加上 H 或 W 再取模是为了处理负数情况(例如从第 0 行向上走会到第 H-1 行)。
      • 循环 N 次,每次根据当前格子颜色执行涂色、转向、移动三步操作。
    3. 边界与细节

      • 题目中网格从 1 开始编号,代码中从 0 开始,两者等价。
      • 方向数组的顺序必须与"上→右→下→左"的顺时针顺序一致,才能保证 dir+1 是顺时针转、dir+3 是逆时针转。
      • 取模时加 H/W 再取模,确保负数下标正确回绕到另一端。
      • N 可能为 0(虽然题目保证 N≥1),但代码逻辑上也可以处理。

    ⏱️ 复杂度分析

    • 时间复杂度O(N)O(N),每次操作 O(1),共 N 次。输出网格 O(HW)。
    • 空间复杂度O(HW)O(HW),用于存储网格。

    💻 标准代码 (C++)

    #include <iostream>
    #include <vector>
    using namespace std;
    int main() {
        int H, W, N;
        cin >> H >> W >> N;
        // 初始化网格,全部为白色 '.'
        vector<vector<char>> grid(H, vector<char>(W, '.'));
        int x = 0, y = 0;          // 当前位置,对应题目中的 (1, 1)
        int dir = 0;                // 当前方向:0=上, 1=右, 2=下, 3=左
        int dx[4] = {-1, 0, 1, 0}; // 方向对应的行偏移量
        int dy[4] = {0, 1, 0, -1}; // 方向对应的列偏移量
        for (int step = 0; step < N; step++) {
            if (grid[x][y] == '.') {       // 当前格子为白色
                grid[x][y] = '#';          // 涂黑
                dir = (dir + 1) % 4;       // 顺时针旋转 90°
            } else {                        // 当前格子为黑色
                grid[x][y] = '.';          // 涂白
                dir = (dir + 3) % 4;       // 逆时针旋转 90°(等价于 (dir-1+4)%4)
            }
            // 环面移动:加上 H/W 再取模确保负数也能正确回绕
            x = (x + dx[dir] + H) % H;
            y = (y + dy[dir] + W) % W;
        }
        // 输出最终网格
        for (int i = 0; i < H; i++) {
            for (int j = 0; j < W; j++) {
                cout << grid[i][j];
            }
            cout << endl;
        }
        return 0;
    }
    
    • 1

    信息

    ID
    775
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    (无)
    递交数
    1
    已通过
    1
    上传者