跳转至

模拟:把题目翻译成代码

什么是模拟?

模拟就是题目干什么,你写什么。题目说「每过一分钟转 90 度」,你的代码就让状态转 90 度;题目说「得分超过 11 分且领先 2 分赢一局」,你的代码就原样判断。

没有高深算法,全靠读题仔细 + 翻译忠实。模拟题丢分从来不是因为不会做,而是因为:看漏一句话、边界差一位、格式差一个空格。

模拟题三板斧

  1. 变量起名跟题走:题目叫「得分」就叫 score,别叫 x
  2. 分步写注释:把题面逐句变成注释,再逐句填代码
  3. 手动模拟小数据:写完先拿样例在纸上走一遍程序,对得上再提交

例题:不高兴的津津

题目描述 津津每天要上学,回家后妈妈还安排了课外班。如果一天上课总时间超过 8 小时,津津就不高兴,而且越超越不高兴。给出 7 天的安排(学校上课小时数、课外班小时数),求津津最不高兴的是哪一天;如果有并列的,输出最靠前的那天。若天天都不超过 8 小时,输出 0。

输入格式 7 行,每行两个整数 \(a\)、\(b\)(学校、课外班,单位小时)。

输出格式 一个整数(1~7 或 0)。

数据范围 \(0 \le a, b \le 10\)。

样例输入 / 样例输出

5 3
6 2
7 2
5 3
5 4
0 4
0 6
3

思路分析 逐句翻译题面:每天总时长 = 学校 + 课外班;超过 8 才有资格比较;「最不高兴」= 总时长最大;「并列取最靠前」= 严格大于才更新。这就是第 2 章「擂台找最大值」的翻版,多了一个「超过 8 才上擂台」的前提。

参考代码

#include <iostream>
using namespace std;

int main() {
    int worstDay = 0;        // 0 表示还没有不高兴的日子
    int worstTime = 8;       // 擂台基线:超过 8 才算不高兴
    for (int day = 1; day <= 7; day++) {
        int a, b;
        cin >> a >> b;
        int total = a + b;
        if (total > worstTime) {   // 严格大于 → 并列时保留更早的天
            worstTime = total;
            worstDay = day;
        }
    }
    cout << worstDay << endl;
    return 0;
}

验证样例:7 天总时长分别是 8 8 9 8 9 4 6——第 3 天 9 小时、第 5 天也是 9,并列取靠前的第 3 天。✅

这就是洛谷 P1085 不高兴的津津,NOIP2004 普及组真题。

模拟的经典变体

模拟题的花样全在状态的表示方式上,你已学过的工具对应一批经典题型:

状态表示 典型题目
数组标记 校门外的树(第 3 章已做)
二维数组棋盘 井字棋胜负判断、铺地毯
计数器 + 循环 约瑟夫报数(第 6 章用队列再战)
多变量维护 乒乓球比分(11 分制 / 21 分制双规则)

洛谷 P1042 乒乓球(NOIP2003 真题)是模拟题的标杆练习:读一串 WE 字符表示得分,同时按 11 分制和 21 分制输出每局比分——规则读细,两遍输出,写完拿样例逐字符核对。

动手试一试

  1. 时钟模拟:读入起始时刻(时:分)和经过分钟数 \(t\)(\(t \le 10^9\)),输出最终时刻(注意取模)
  2. 读入 \(n\) 和 \(n\) 个体温,输出第一次超过 \(37.3\) 的序号;都不超输出 OK
  3. 铺地毯(洛谷 P1003,NOIP2011 提高 T1 但难度不高):平面上依次铺 \(n\) 张矩形地毯,问最上面盖住点 \((x,y)\) 的是第几张
  4. 挑战 P1042 乒乓球:注意「达到 11 分且领先 2 分」才结束一局,最后一局可能没打完也要输出

下一课:每一步都拿眼前最好的——贪心。