1 条题解
-
0
📝 题目大意
有一个 H×W 的网格(初始全白),网格边界是循环的(环面)。从 (1,1) 面朝上方出发,重复 N 次:若当前格子为白色则涂黑并顺时针转 90° 前进一格,若为黑色则涂白并逆时针转 90° 前进一格。输出最终网格状态。
💡 解题思路
-
题目分析:这是一道经典的"兰顿蚂蚁"(Langton's Ant)模拟题。约束条件 H, W ≤ 100,N ≤ 1000,数据范围很小,直接模拟即可,无需优化。
-
算法推导:
- 用
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) % H,y = (y + dy[dir] + W) % W,加上 H 或 W 再取模是为了处理负数情况(例如从第 0 行向上走会到第 H-1 行)。 - 循环 N 次,每次根据当前格子颜色执行涂色、转向、移动三步操作。
- 用
-
边界与细节:
- 题目中网格从 1 开始编号,代码中从 0 开始,两者等价。
- 方向数组的顺序必须与"上→右→下→左"的顺时针顺序一致,才能保证
dir+1是顺时针转、dir+3是逆时针转。 - 取模时加 H/W 再取模,确保负数下标正确回绕到另一端。
- N 可能为 0(虽然题目保证 N≥1),但代码逻辑上也可以处理。
⏱️ 复杂度分析
- 时间复杂度:,每次操作 O(1),共 N 次。输出网格 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
- 上传者