Skip to content

18. 模拟算法:照本宣科

前置学习:二维数组字符串

很多时候,算法题目并没有要求你找规律或者列方程,它只是塞给你一大堆极其繁琐的规则,让你写一个程序来充当“裁判”或者“执行者”。 这种题目怎么说,代码就怎么按部就班去实现的算法,叫做模拟 (Simulation)

1. 模拟题的特点

  1. 思维难度低:不需要你灵光一闪想出绝妙的数学公式。
  2. 代码量极大:通常涉及大量的 if-else 分支、二维数组操作和状态标记。
  3. 极易翻车:题目规则又多又细,漏掉任何一个边界条件(比如越界、特殊字符),直接爆零。

2. 经典实战:扫地机器人

题目描述: 有一个 $5 \times 5$ 的空房间(用 0 到 4 的二维坐标表示)。机器人初始位置在正中心 (2, 2)。 现在给你一串用字符串表示的指令,U 代表上移,D 代表下移,L 代表左移,R 代表右移。 如果机器人撞到墙壁(越界),它会停在原地忽略该指令。求机器人最终停在哪里的坐标。

解题思路(纯逻辑翻译): 遇到 U 就让行坐标减 1;遇到 D 就让行坐标加 1... 每次移动前,检查一下有没有撞墙即可。

cpp
#include <bits/stdc++.h>
using namespace std;

int main() {
    int x = 2; // 行坐标 (纵向)
    int y = 2; // 列坐标 (横向)
    string commands = "UULDRRRDD"; // 指令串
    
    // 遍历每一个指令
    for (int i = 0; i < commands.size(); i++) {
        char cmd = commands[i];
        
        // 模拟移动,同时利用 if 进行墙壁防撞检查 (边界判定)
        if (cmd == 'U' && x > 0) {
            x--; // 向上移动,行号减小
        } else if (cmd == 'D' && x < 4) {
            x++; // 向下移动,行号增加
        } else if (cmd == 'L' && y > 0) {
            y--; // 向左移动,列号减小
        } else if (cmd == 'R' && y < 4) {
            y++; // 向右移动,列号增加
        }
    }
    
    cout << "最终坐标是: (" << x << ", " << y << ")" << endl;
    return 0;
}

3. 🛡️ 模拟题避坑指南

在做复杂的模拟题(如扫雷、约瑟夫环、大模拟考试)时,请死守以下原则:

  1. 先画图,后写码:在草稿纸上把坐标系画出来,确认向左是减还是加,不要凭空想象。
  2. 分解任务:如果题目太复杂,把代码拆分成几个功能明确的逻辑块。
  3. 极端数据测试:写完后,专门输入那些“一上来就撞墙”、“原地不动”的极端指令,看程序会不会崩溃。

4. 动手实践

md
1. 打开左下角的代码沙盒。
2. 试着修改上面的扫地机器人代码。
3. 增加新规则:如果机器人的当前坐标来到了 `(0, 0)`(房间左上角的终点),立刻打印“到达终点!”,并用 `break` 结束所有剩余的指令。
💻 运行代码

C++ 在线评测沙盒

📥 标准输入 (cin):
📤 终端输出 (cout):