GESP C++ 四级真题详细分析讲解
GESP C++ 四级是从“基础语法 + 一维数组”过渡到“二维数组 + 排序应用”的阶段。
和三级相比,四级最明显的变化是:
1. 数据从一维变成二维 2. 排序从简单排序变成多关键字排序 3. 题目更强调下标、坐标、比较规则和模拟过程
按照 GESP 四级的知识范围,核心内容主要有两大类:
• 简单二维数组 • 多关键字排序
注意:GESP 四级一般不应涉及递归、动态规划、二分、图论、GCD、LCM、质因数分解、复杂 STL 容器等内容。
一、GESP C++ 四级知识点定位
1. 四级核心知识点
sort |
2. 四级与三级的区别
举例来说:
三级常见题:
输入 n 个数,统计某个数出现几次。四级常见题:
输入 n 行 m 列的矩阵,统计每一行、每一列的和。三级排序可能只是:
把一组数从小到大排序。四级排序可能变成:
学生按总分从高到低排序,总分相同按语文分从高到低,仍相同按编号从小到大。二、四级真题整体特点
1. 题目难度特点
GESP C++ 四级题目一般有以下特点:
• 代码量通常在 30 到 80 行 • 题目不会太复杂,但细节较多 • 常见输入规模不大,暴力遍历通常可以通过 • 重点考查: ◦ 二维数组下标 ◦ 行列循环顺序 ◦ 坐标转换 ◦ 排序比较函数 ◦ 结构体数组使用
2. 常见失分点
a[i][j]i 是行,j 是列 | |
i <= ni < n 混用 | |
a[105][105] | |
n × m,转置后是 m × n | |
>,升序应写 < | |
scoreid、sum 等变量含义要清楚 |
三、模块一:二维数组真题分析
二维数组是 GESP 四级最重要的内容之一。它的本质是“表格”。
例如:
3 行 4 列矩阵:1 2 3 45 6 7 89 1 2 3可以用:
int a[105][105];来存储。
1. 常考题型一:矩阵输入与输出
题型描述
输入一个 n 行 m 列的矩阵,按照要求输出。
核心代码
int n, m;cin >> n >> m;int a[105][105];for (int i = 1; i <= n; i++) {for (int j = 1; j <= m; j++) { cin >> a[i][j]; }}输出:
for (int i = 1; i <= n; i++) {for (int j = 1; j <= m; j++) { cout << a[i][j] << " "; } cout << endl;}考查重点
• 双重循环 • 行列顺序 • 二维数组下标
易错点
很多同学会把行列写反:
for (int i = 1; i <= m; i++) {for (int j = 1; j <= n; j++) { cin >> a[i][j]; }}如果题目说的是 n 行 m 列,一般应写:
i = 1 到 nj = 1 到 m2. 常考题型二:矩阵总和、行和、列和
题型描述
给定一个矩阵,求:
• 所有元素之和 • 每一行的和 • 每一列的和 • 最大行和 / 最大列和
2.1 求矩阵总和
示例代码
#include<bits/stdc++.h>usingnamespace std;intmain(){int n, m; cin >> n >> m;int a[105][105];int sum = 0;for (int i = 1; i <= n; i++) {for (int j = 1; j <= m; j++) { cin >> a[i][j]; sum += a[i][j]; } } cout << sum << endl;return0;}思路
读入时直接累加即可,不一定非要读完后再算。
2.2 求每一行的和
for (int i = 1; i <= n; i++) {int rowSum = 0;for (int j = 1; j <= m; j++) { rowSum += a[i][j]; } cout << rowSum << endl;}这里固定的是行 i,变化的是列 j。
2.3 求每一列的和
for (int j = 1; j <= m; j++) {int colSum = 0;for (int i = 1; i <= n; i++) { colSum += a[i][j]; } cout << colSum << endl;}这里固定的是列 j,变化的是行 i。
2.4 行和与列和的区别
i | j | |
j | i |
很多四级同学在这里容易混。
3. 常考题型三:矩阵最大值及其位置
题型描述
输入一个矩阵,找到最大值以及它所在的位置。
示例代码
#include<bits/stdc++.h>usingnamespace std;intmain(){int n, m; cin >> n >> m;int a[105][105];for (int i = 1; i <= n; i++) {for (int j = 1; j <= m; j++) { cin >> a[i][j]; } }int maxValue = a[1][1];int maxRow = 1, maxCol = 1;for (int i = 1; i <= n; i++) {for (int j = 1; j <= m; j++) {if (a[i][j] > maxValue) { maxValue = a[i][j]; maxRow = i; maxCol = j; } } } cout << maxValue << " " << maxRow << " " << maxCol << endl;return0;}易错点
不要把最大值初始成 0。
如果矩阵中可能有负数:
int maxValue = 0;可能会出错。
更稳妥写法是:
int maxValue = a[1][1];4. 常考题型四:矩阵转置
题型描述
给定一个 n × m 的矩阵,输出它的转置矩阵。
原矩阵:
1 2 34 5 6是 2 × 3。
转置后:
1 42 53 6是 3 × 2。
核心规律
原来的:
a[i][j]转置后变成:
a[j][i]示例代码
#include<bits/stdc++.h>usingnamespace std;intmain(){int n, m; cin >> n >> m;int a[105][105];for (int i = 1; i <= n; i++) {for (int j = 1; j <= m; j++) { cin >> a[i][j]; } }for (int j = 1; j <= m; j++) {for (int i = 1; i <= n; i++) { cout << a[i][j] << " "; } cout << endl; }return0;}重点理解
输出时:
• 原来的列 j变成新的行• 原来的行 i变成新的列
所以外层循环是:
j = 1 到 m内层循环是:
i = 1 到 n5. 常考题型五:主对角线与副对角线
这类题通常出现在方阵中,也就是 n × n 的矩阵。
5.1 主对角线
主对角线位置满足:
i == j例如:
a[1][1]a[2][2]a[3][3]代码:
int sum = 0;for (int i = 1; i <= n; i++) { sum += a[i][i];}5.2 副对角线
副对角线位置满足:
i + j == n + 1也就是:
j = n - i + 1代码:
int sum = 0;for (int i = 1; i <= n; i++) { sum += a[i][n - i + 1];}5.3 两条对角线之和
int sum = 0;for (int i = 1; i <= n; i++) { sum += a[i][i]; sum += a[i][n - i + 1];}if (n % 2 == 1) { sum -= a[n / 2 + 1][n / 2 + 1];}为什么要减一次?
当 n 是奇数时,中心点同时属于主对角线和副对角线。
例如 3 × 3:
1 2 34 5 67 8 9中心 5 被加了两次,所以要减一次。
6. 常考题型六:简单网格模拟
题型描述
给定一个二维网格,根据规则修改某些格子或统计某些格子。
常见形式:
• 标记某一行、某一列 • 判断某个格子的上下左右 • 统计周围满足条件的格子数量 • 简单地图移动
6.1 四方向相邻格子
对于格子 (x, y),上下左右分别是:
(x - 1, y) | |
(x + 1, y) | |
(x, y - 1) | |
(x, y + 1) |
可以写成方向数组:
int dx[4] = {-1, 1, 0, 0};int dy[4] = {0, 0, -1, 1};使用:
for (int k = 0; k < 4; k++) {int nx = x + dx[k];int ny = y + dy[k];if (nx >= 1 && nx <= n && ny >= 1 && ny <= m) {// 合法格子 }}注意
这里的方向数组只是普通数组和循环,不是图论搜索。GESP 四级可以出现简单的相邻格子判断,但不应出现 BFS、DFS 这类图论算法。
6.2 统计周围格子
例如统计每个格子上下左右有多少个 1:
int cnt = 0;for (int k = 0; k < 4; k++) {int nx = i + dx[k];int ny = j + dy[k];if (nx >= 1 && nx <= n && ny >= 1 && ny <= m) {if (a[nx][ny] == 1) { cnt++; } }}易错点
一定要先判断坐标是否合法,再访问数组:
错误写法:
if (a[nx][ny] == 1 && nx >= 1 && nx <= n)这样可能在 nx 越界时已经访问了数组,导致错误。
正确写法:
if (nx >= 1 && nx <= n && ny >= 1 && ny <= m) {if (a[nx][ny] == 1) { cnt++; }}四、模块二:多关键字排序真题分析
多关键字排序是 GESP 四级的另一个核心。
所谓“多关键字排序”,就是排序时不只看一个条件,而是按多个条件依次比较。
1. 什么是多关键字排序?
例如学生成绩排序:
规则如下:
1. 总分高的排前面 2. 总分相同,语文分高的排前面 3. 总分和语文都相同,编号小的排前面
这就叫多关键字排序。
2. 结构体基础
如果每个学生有多个属性,用结构体存储最方便:
structStudent {int id;int chinese;int math;int english;int total;};定义数组:
Student a[105];读入:
for (int i = 1; i <= n; i++) { a[i].id = i; cin >> a[i].chinese >> a[i].math >> a[i].english; a[i].total = a[i].chinese + a[i].math + a[i].english;}3. sort 自定义比较函数
基本格式
boolcmp(Student x, Student y){return x.total > y.total;}使用:
sort(a + 1, a + n + 1, cmp);如果数组从 0 开始:
sort(a, a + n, cmp);4. 常考题型一:成绩排序
题型描述
输入若干学生的成绩,按照总分从高到低排序,如果总分相同,再按某一科成绩排序,最后按编号排序。
示例代码
#include<bits/stdc++.h>usingnamespace std;structStudent {int id;int chinese;int math;int english;int total;};boolcmp(Student a, Student b){if (a.total != b.total) {return a.total > b.total; // 总分高的在前 }if (a.chinese != b.chinese) {return a.chinese > b.chinese; // 语文高的在前 }return a.id < b.id; // 编号小的在前}intmain(){int n; cin >> n; Student stu[305];for (int i = 1; i <= n; i++) { stu[i].id = i; cin >> stu[i].chinese >> stu[i].math >> stu[i].english; stu[i].total = stu[i].chinese + stu[i].math + stu[i].english; }sort(stu + 1, stu + n + 1, cmp);for (int i = 1; i <= n; i++) { cout << stu[i].id << " " << stu[i].total << endl; }return0;}5. 比较函数怎么写?
比较函数的核心问题是:
"
如果 a 应该排在 b 前面,就返回 true。
例如:
return a.total > b.total;表示总分大的排前面。
return a.id < b.id;表示编号小的排前面。
6. 多关键字排序模板
推荐背熟这个模板:
boolcmp(Node a, Node b){if (a.x != b.x) return a.x > b.x;if (a.y != b.y) return a.y < b.y;return a.id < b.id;}含义:
1. 先按 x从大到小2. x相同按y从小到大3. 还相同按 id从小到大
7. 常考题型二:排名问题
题型描述
按照分数排序后,输出前若干名,或者输出每个人的排名。
四级阶段常见的是简单排序后输出,不会涉及复杂的数据结构。
示例:输出前 5 名
sort(a + 1, a + n + 1, cmp);for (int i = 1; i <= 5 && i <= n; i++) { cout << a[i].id << " " << a[i].score << endl;}注意
如果题目要求“同分同名次”,需要额外处理。但四级常见题一般只是排序后按顺序输出。
8. 常考题型三:按字典序或字符串排序
有时排序对象中包含字符串,例如姓名。
structPerson { string name;int score;};比较函数:
boolcmp(Person a, Person b){if (a.score != b.score) return a.score > b.score;return a.name < b.name;}string 可以直接比较:
"a" < "b""abc" < "abd"这是按照字典序比较。
五、四级真题常见综合题型
GESP 四级有时会把二维数组和排序结合起来,但仍然不会太复杂。
1. 题型一:统计每一行成绩并排序
题型描述
有 n 个学生,每个学生有 m 门成绩,求每个人总分,并按总分排序。
分析
输入可以看作二维表:
学生1:成绩1 成绩2 成绩3学生2:成绩1 成绩2 成绩3...可以不用真正存整个二维数组,只需要读入时累加总分。
示例代码
#include<bits/stdc++.h>usingnamespace std;structStudent {int id;int sum;};boolcmp(Student a, Student b){if (a.sum != b.sum) return a.sum > b.sum;return a.id < b.id;}intmain(){int n, m; cin >> n >> m; Student a[105];for (int i = 1; i <= n; i++) { a[i].id = i; a[i].sum = 0;for (int j = 1; j <= m; j++) {int x; cin >> x; a[i].sum += x; } }sort(a + 1, a + n + 1, cmp);for (int i = 1; i <= n; i++) { cout << a[i].id << " " << a[i].sum << endl; }return0;}2. 题型二:矩阵中找特殊位置
题型描述
给定一个矩阵,找满足某种条件的位置,例如:
• 是所在行最大值 • 是所在列最小值 • 周围格子满足某种条件 • 某一行或某一列的和最大
分析方法
这类题关键是拆成两步:
1. 枚举每一个位置 2. 判断这个位置是否满足条件
示例:判断某个元素是否是所在行最大值
bool ok = true;for (int j = 1; j <= m; j++) {if (a[i][j] > a[i][pos]) { ok = false; }}如果还要判断它是否是所在列最小值:
for (int k = 1; k <= n; k++) {if (a[k][pos] < a[i][pos]) { ok = false; }}六、四级真题解题流程
遇到 GESP 四级题,可以按下面步骤分析。
第一步:判断题型
先看题目数据形式:
如果是表格 / 矩阵 / 棋盘
基本属于二维数组题。
常见关键词:
n 行 m 列矩阵方阵棋盘地图表格行列对角线上下左右如果是学生 / 选手 / 商品 / 多个属性
基本属于结构体排序题。
常见关键词:
成绩排名编号姓名总分按……排序若相同则……优先级第二步:确定存储方式
int a[105][105]char mp[105][105] | |
struct Student | |
第三步:写清楚循环范围
二维数组最重要的是循环边界:
for (int i = 1; i <= n; i++) {for (int j = 1; j <= m; j++) {// a[i][j] }}其中:
• i表示第几行• j表示第几列
第四步:排序题先写比较规则
排序题不要急着写代码,先把规则翻译成比较函数。
例如题目说:
总分高的在前;总分相同,编号小的在前。就写:
boolcmp(Node a, Node b){if (a.sum != b.sum) return a.sum > b.sum;return a.id < b.id;}七、四级常见代码模板
模板一:二维数组输入
int n, m;int a[105][105];cin >> n >> m;for (int i = 1; i <= n; i++) {for (int j = 1; j <= m; j++) { cin >> a[i][j]; }}模板二:矩阵遍历
for (int i = 1; i <= n; i++) {for (int j = 1; j <= m; j++) {// 处理 a[i][j] }}模板三:行和
for (int i = 1; i <= n; i++) {int sum = 0;for (int j = 1; j <= m; j++) { sum += a[i][j]; } cout << sum << endl;}模板四:列和
for (int j = 1; j <= m; j++) {int sum = 0;for (int i = 1; i <= n; i++) { sum += a[i][j]; } cout << sum << endl;}模板五:转置输出
for (int j = 1; j <= m; j++) {for (int i = 1; i <= n; i++) { cout << a[i][j] << " "; } cout << endl;}模板六:结构体排序
structNode {int id;int x;int y;};boolcmp(Node a, Node b){if (a.x != b.x) return a.x > b.x;if (a.y != b.y) return a.y < b.y;return a.id < b.id;}模板七:排序调用
sort(a + 1, a + n + 1, cmp);八、四级考试常见题型总结
1. 二维数组类
a[i][j] 时交换行列顺序 | |
i == j,副对角线 i + j == n + 1 | |
2. 多关键字排序类
if | |
string | |
id 保证顺序明确 |
九、四级真题中的重点难点
1. 二维数组难点:坐标意识
很多同学学二维数组时最大的问题不是不会写循环,而是没有坐标意识。
建议始终记住:
a[i][j]表示:
第 i 行,第 j 列不要把 i 和 j 的含义混掉。
2. 二维数组难点:边界判断
如果题目涉及上下左右,一定要判断:
nx >= 1 && nx <= n && ny >= 1 && ny <= m否则可能越界。
3. 排序难点:比较函数返回值
比较函数不是判断谁“大”,而是判断:
"
第一个参数是否应该排在第二个参数前面。
例如:
boolcmp(Node a, Node b){return a.score > b.score;}意思是:
如果 a 的分数比 b 高,那么 a 应该排在 b 前面。4. 排序难点:多条件顺序
题目中条件的先后顺序非常重要。
例如:
先按总分从高到低;总分相同按语文从高到低;语文也相同按编号从小到大。代码必须按这个顺序写:
if (a.total != b.total) return a.total > b.total;if (a.chinese != b.chinese) return a.chinese > b.chinese;return a.id < b.id;不能把编号放到前面比较。
十、四级真题难度分布
一套 GESP C++ 四级题通常可以这样理解:
当然具体年份会有变化,但整体不会脱离“二维数组 + 多关键字排序”的主线。
十一、四级备考重点
第一阶段:二维数组基础
必须熟练:
• 输入 n × m矩阵• 输出矩阵 • 求总和 • 求行和 • 求列和 • 找最大值和位置
目标是看到矩阵题能马上写出双重循环。
第二阶段:二维数组进阶
重点练:
• 矩阵转置 • 主对角线 / 副对角线 • 上下左右相邻格子 • 简单网格模拟 • 行列最大最小值
第三阶段:排序专项
重点练:
• 结构体定义 • sort使用• 自定义比较函数 • 多关键字排序 • 成绩排序 • 编号排序 • 字符串字典序排序
第四阶段:综合真题训练
做真题时建议:
1. 先独立思考题型 2. 判断是二维数组还是排序 3. 写出核心循环或比较函数 4. 再补完整代码 5. 做完后检查边界和排序规则
十二、从四级到五级的衔接
GESP 四级通过后,五级会进入明显更难的阶段,主要包括:
• GCD / LCM • 质因数分解 • 筛法 • 快速幂 • 二分查找 / 二分答案 • 前缀和与差分 • 更复杂的贪心 • 哈希表应用
因此,四级和五级之间的跨度较大。
如果你四级能稳定达到 90 分以上,可以开始学习五级内容。
如果四级只有 60 到 80 分,建议先不要急着进入五级,应重点补:
• 二维数组行列遍历 • 矩阵转置 • 对角线处理 • 排序比较函数 • 结构体数组
十三、四级考前检查清单
考前可以问自己以下问题:
二维数组部分
• 我能不能独立写出 n × m矩阵输入?• 我是否清楚 a[i][j]中i是行,j是列?• 我能不能求每一行的和? • 我能不能求每一列的和? • 我能不能输出转置矩阵? • 我是否知道主对角线和副对角线的下标规律? • 我能不能判断上下左右坐标是否合法?
排序部分
• 我会不会定义结构体? • 我会不会写 sort(a + 1, a + n + 1, cmp)?• 我是否理解 cmp(a, b)返回 true 的含义?• 我能不能写出总分降序、编号升序? • 我能不能处理三个以上关键字的排序? • 我是否会用 string进行字典序比较?
十四、总结
GESP C++ 四级的核心可以概括为两句话:
"
二维数组题,看清行列,用双重循环处理。排序题,看清优先级,用结构体和比较函数实现。
四级并不追求复杂算法,而是考查你是否能熟练处理“表格数据”和“多条件排序”。
最重要的两个能力是:
1. 二维数组坐标能力 ◦ 行、列、对角线、上下左右 2. 多关键字比较能力 ◦ 谁优先、升序还是降序、相同怎么办
如果这两部分都熟练,GESP C++ 四级基本可以稳定通过,并且能为五级的数论、二分、前缀和等内容打好基础。