ARTICLE · 1179552
CSP复赛指南(4) |模拟题:复赛最容易拿满的基础大题
很多同学觉得算法题必须掌握高级数据结构、DP、图论。但 CSP-J/S 复赛里,模拟题永远是第一道大题,是保底拿分的核心!模拟题没有复杂算法,核心一句话:严格按照题目描述,一步一步用代码复现题目过程。难点不在于算法,而在于:细心、边界处理、读题、代码实现能力。很多人不是不会做,而是读漏条件、写错变量、漏掉特殊样例,白白丢分。
什么是模拟题?
模拟题 = 把题目文字描述的现实过程,翻译成代码。 不需要你想巧妙公式,题目怎么说,代码就怎么做。 ✅ 特点:
算法难度低,只用到循环、数组、字符串 代码量偏大,细节极多 坑点大多藏在边界、特殊输入、顺序问题 复赛第一题高频出场,是拿基础分的必争之地
❌ 模拟题最常见丢分原因:
读题跳字,漏掉隐藏条件 变量混淆,下标从 0 还是从 1 搞混 没有单独测试样例,直接提交 忽略极端数据(空输入、最大值、循环结束条件) 中途修改代码,引入新 bug
做题口诀:先读题,画流程;小样例,手推演;写代码,分步测
为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯。一共有 n 张地毯,编号从 1 到 n。现在将这些地毯按照编号从小到大的顺序平行于坐标轴先后铺设,后铺的地毯覆盖在前面已经铺好的地毯之上。
地毯铺设完成后,组织者想知道覆盖地面某个点的最上面的那张地毯的编号。注意:在矩形地毯边界和四个顶点上的点也算被地毯覆盖。
输入共 n + 2 行。
第一行,一个整数 n,表示总共有 n张地毯。
接下来的 n 行中,第 i+1行表示编号 i 的地毯的信息,包含四个整数 a ,b ,g ,k,每两个整数之间用一个空格隔开,分别表示铺设地毯的左下角的坐标 (a, b) 以及地毯在 x 轴和 y 轴方向的长度。
第 n + 2 行包含两个整数 x 和 y,表示所求的地面的点的坐标 (x, y)。
-1。#include<iostream>using namespace std;const int MAXN = 10005;int x[MAXN], y[MAXN], g[MAXN], k[MAXN];intmain(){int n;cin >> n;for(int i = 1; i <= n; i++){cin >> x[i] >> y[i] >> g[i] >> k[i];}int a,b;cin >> a >> b;// 倒序查找,找到第一个覆盖点的地毯int ans = -1;for(int i = n; i >= 1; i--){if(a >= x[i] && a <= x[i]+g[i] && b >= y[i] && b <= y[i]+k[i]){ans = i;break;}}cout << ans << endl;return 0;}
【题目大意】
轩轩和凯凯正在玩一款叫龙虎斗的游戏。游戏有 n 个战场,编号 (1 ~ n),每个战场有一个初始兵力 (s_i)。龙在第 m 号战场,龙的势力:所有编号 ≤ m 的战场兵力总和;虎在第 m 号战场,虎的势力:所有编号 ≥ m 的战场兵力总和。
现在召唤一个神兵,兵力为 p。神兵可以放到任意一个战场(包括 m 号战场)。要求:放置之后,龙势力与虎势力差值的绝对值尽可能小。如果有多个战场满足最优解,选择编号最小的战场。
输入:第一行:整数 n第二行:n 个整数 (s_1,s_2...s_n)第三行:两个整数 (m,p)
输出:一个整数,神兵放置的战场编号。
【题目分析】
- 龙气势 ql:遍历 (i=1) 到 (m-1),
ql += c[i]*(m-i)- 虎气势 qh:遍历 (i=m+1) 到 n,
qh += c[i]*(i-m) - 情况①:
qh > ql(虎更强):只能枚举 m 左边所有战场 (i<m)。放到 i 之后,新龙气势 = (ql + s_2 * (m-i)),虎气势不变。
计算新差值,如果比当前
cha更小,更新最小差值,记录位置 i。- 情况②:
ql >= qh(龙更强或相等):只能枚举 m 右边所有战场 (i>m)。放到 i 之后,新虎气势 = (qh + s_2 * (i-m)),龙气势不变。
计算新差值,如果比当前
cha更小,更新最小差值,记录位置 i。模拟核心:严格跟着游戏流程一步步模拟,气势不是兵力,是兵力乘以距离!
很多选手读题直接忽略距离系数,直接当成兵力求和,整题爆零。
【参考答案】
#include<cmath>#include<iostream>#include<algorithm>using namespace std;long long n,c[100008],m,p1,s1,s2;intmain(){cin>>n;for(int i=1;i<=n;i++){cin>>c[i];}cin>>m>>p1>>s1>>s2;c[p1]+=s1;long long ql=0,qh=0;for(int i=1;i<m;i++){ //计算龙的初始气势值ql+=c[i]*(m-i);}for(int i=m+1;i<=n;i++){ //计算虎的初始气势值qh+=c[i]*(i-m);}//cout<<qh<<" "<<ql<<endl;bool yeshu=false,yeslong=false;if(qh>ql) yeshu=true; //判断龙虎大小关系else yeslong=true;long long p=m,cha=abs(ql-qh);if(yeshu==true){for(int i=1;i<m;i++){long long l2=ql+s2*(m-i);if(cha>abs(qh-l2)){cha=abs(qh-l2);p=i;}}}else{for(int i=m+1;i<=n;i++){long long h2=qh+s2*(i-m);if(cha>abs(ql-h2)){cha=abs(ql-h2);p=i;}}}cout<<p;return 0;}
【题目大意】
华华记录乒乓球每一球的胜负。W代表华华拿到 1 分,L代表对手拿到 1 分,E代表记录结束。 需要分别按照 11 分制 和 21 分制,模拟所有对局的比分。
✅ 一局结束规则(核心!):
有一方 ≥ 获胜基础分(11 分制是 11,21 分制是 21) - 双方分差 ≥ 2
两个条件同时满足,本局立刻结束,输出本局比分,然后开启新一局(比分重置为 0:0)。 如果读到 E 结束时,这一局还没有打完,也要输出当前未结束的比分。
输入:一串由W、L组成的字符,以E结尾。 输出: 先输出 11 分制下每一局比分;空一行; 再输出 21 分制下每一局比分。
样例:WWWWWWWWWWWWWWWWWWWWWWLW11 分制:11:011:01:121 分制:21:02:1
本题属于事件流程模拟,逐球读取,两套计分规则分开模拟。
读取字符,逐个处理每一分,遇到 E停止。写一个通用模拟函数,传入获胜门槛(11 或者 21),返回所有局的比分。避免写两份几乎一样的代码,减少 bug。 一局内维护两个变量: w华华分数,l对手分数。读到 W:w++;读到 L:l++ 判断本局是否结束: (w>=门槛 || l>=门槛) && abs(w-l)>=2如果本局结束:输出比分,重置 w,l=0,开启下一局 全部字符读完后,如果当前局还没结束,必须输出当前比分(很多选手漏掉这个,丢分) 11 分制全部输出完成后,输出一个空行,再输出 21 分制结果,输出格式坑点!
模拟核心:按顺序一分一分推演比赛进程,严格遵守比赛结束条件;两套规则共用一套模拟逻辑。
#include<iostream>#include<cmath>using namespace std;char buf[1000005];int len = 0;// 根据数组模拟voidsimulate(int winScore){int w = 0, l = 0;for(int i = 0; i < len; i++){char ch = buf[i];if(ch == 'E') break;if(ch == 'W') w++;else if(ch == 'L') l++;if( (w >= winScore || l >= winScore) && abs(w - l) >= 2 ){cout << w << ":" << l << endl;w = 0;l = 0;}}cout << w << ":" << l << endl;}intmain(){char ch;// 第一步:读取全部字符,存入buf,跳过空格换行while( cin>>ch && ch!='E' ){buf[len++] = ch;}simulate(11);cout << endl;simulate(21);return 0;}
在 CSP-J 复赛里,模拟题几乎固定是第一题,是整场考试的保底得分基石。
模拟题不考察复杂高级算法,不需要掌握搜索、DP、图论,只考验读题能力、细心程度和基础代码功底。只要认真读题、注意细节,绝大多数同学都有机会拿到满分。
复赛想要拿到省一 / 省二,首先就要把模拟题稳稳拿下。一旦模拟题丢大量分数,后面难题再想追回分数会非常困难;同时,模拟题也是建立考场信心的关键,顺利写完第一题,能让你更好地进入状态,继续完成后面的题目。
一句话概括:模拟题是复赛的基本盘,基本盘稳住,才有冲奖的机会。















































































