CCF-GESP 等级考试 2025年12月认证C++四级真题解析
1 单选题(每题 2 分,共 30 分)
第1题 小杨想让指针 p 指向整数变量 x ,正确写法是( )。
A. int p = &x; B. int *p = x; C. int *p = &x; D. p = *x;
解析:答案C。(1)正确声明指针:int *p = &x; 将指针 p 指向变量 x 的地址;(2)输出变量值:通过解引用 *p 输出 x 的值。所以C正确,其他语法错误或逻辑错误。故选C。
第2题 小杨写了如下的指针接力程序,程序执行完后变量a、*p1和*p2的值分别是( )。
int a = 5; int* p1 = &a; int* p2 = p1; *p2 = 10;A. 5 10 10 B. 5 10 15 C. 10 10 10 D. 5 5 10
解析:答案C。p1为指向a的指针,p2复制了p1(指向同一地址),对*p2赋值等于对a赋值,*p1也同值。所以a、*p1和*p2的值分别是,10、10、10。故选C。
第3题 小杨用一个二维数组表示棋盘,其中 1 表示有棋子,0 表示没有棋子。他想知道第2 行 第3 列有没有棋子,可采用的代码是:( )。
int a[3][4] = { {1, 0, 1, 0}, {0, 1, 0, 1}, {1, 1, 0, 0} };A. cout << a[1, 2] << endl; B. cout << a[1][2] << endl;
C. cout << a(1, 2) << endl; D. cout << a{1}{2} << endl;
解析:答案B。C++数组的下标是从0开始,第一个元素是0行0列,对第2 行第3 列表示为a[1][2]。故选B。
第4题 执行完下面的代码后, *(p + 5) 和 arr[1][1] 的值分别是( )。
int arr[3][4] = {{1,2,3,4}, {5,6,7,8}, {9,10,11,12}}; int* p = &arr[0][0];A. 5 6 B. 6 5 C. 5 5 D. 6 6
解析:答案D。C++二维数组是按行连续排的,p指向arr的首地址,指向第一个元素,p+5指向第6个元素,即a[1][1],*(p+5)与a[1][1]同地址,输出6 6。故选D。
第5题 执行完下面的代码后,sum 的值是( )。
int arr[2][3][2] = { {{1,2}, {3,4}, {5,6}}, {{7,8}, {9,10}, {11,12}} }; int sum = 0; for(int i = 0; i < 2; i++) for(int j = 0; j < 3; j++) for(int k = 0; k < 2; k++) if((i+j+k) % 2 == 0) sum += arr[i][j][k];A. 36 B. 39 C. 78 D. 30
解析:答案B。C++三维数组是按行连续排的,满足求和的条件是不,是I,j,k分别为0,0,0,0,1,1,0,2,0,1,0,1,1,1,0,1,2,1,1+4+5+8+9+12=39。故选B。
第6题 执行完下面的代码后,输出是( )。
int a = 1; void test() { int a = 2; { int a = 3; a++; } a++; cout << a << " "; } int main() { test(); cout << a; return 0; }A. 3 1 B. 4 1 C. 3 2 D. 4 2
解析:答案A。第1行的a是全局变量,第14行调用test()函数,函数中有多个局部变量a,第4行定义的局部变量a=2,第5~8行中一对“{}”中定义a是局部变量,离开“}”就“消失”,恢复第4定义的a,第9行的a++执行的是第4行定义的a,所以输出3和空格,第15行输出的是全局变量a,值为1。故选A。
第7题 执行完下面的代码后,a、b和c的值分别是( )。
void byValue(int x) { x = 100; } void byRef(int& x) { x = 200; } void byPointer(int* x) { *x = 300; } int main() { int a = 1, b = 2, c = 3; byValue(a); byRef(b); byPointer(&c); return 0; }A. 100 200 300 B. 1 2 3 C. 1 200 300 D. 1 2 300
解析:答案C。byValue(int x)是值传递,所以修改x不影响a的,a仍为1;byRef(int& x)为引用传递,传递是变量地址,修改x等于修改b,所以b为200;byPointer(int* x)为指针传递,x指向c的地址。修改*x等于修改c,所以c为300。a、b和c的值分别是1、200、300。故选C。
第8题 运行如下代码会输出( )。
struct Point { int x, y; }; struct Rectangle { Point topLeft; Point bottomRight; }; int main() { Rectangle rect = {{10, 10}, {20, 20}}; rect.topLeft.x = 5; Point* p = &rect.bottomRight; p->y = 5; cout << rect.topLeft.x + rect.bottomRight.y; return 0; }A. 10 B. 30 C. 15 D. 20
解析:答案A。代码分析:
结构体定义:Point 结构体包含两个整型成员 x 和 y;Rectangle 结构体包含两个 Point 类型成员:topLeft 和 bottomRight。
初始化:Rectangle rect = {{10, 10}, {20, 20}};
rect.topLeft 初始化为 (10, 10);rect.bottomRight 初始化为 (20, 20)。
修改操作:rect.topLeft.x = 5; (将rect 的 topLeft 的 x 坐标修改为 5);Point* p = &rect.bottomRight; (指向rect 的 bottomRight),p->y = 5; (通过指针修改 rect 的 bottomRight 的 y 坐标为 5)
输出计算:cout << rect.topLeft.x + rect.bottomRight.y;
rect.topLeft.x 现在为 5,rect.bottomRight.y 现在为 5。
因此,输出结果为 5 + 5 = 10。故选A。
第9题 给定函数 climbStairs(int n) 的定义如下,则 climbStairs(5) 的返回的值是( )。
int climbStairs(int n) { if(n <= 2) return n; int a = 1, b = 2; for(int i = 3; i <= n; i++) { int temp = a + b; a = b; b = temp; } return b; }A. 5 B. 8 C. 13 D. 10
解析:答案B。当n=5时:i=3时,a=2,b=3;i=4,a=3,b=5;i=5时,a=5,b=8。故选B。
第10题 对如下4个扑克牌进行排序,
struct Card { int value; char suit; // 花色 }; Card cards[4] = {{5,'A'}, {3,'B'}, {5,'C'}, {3,'D'}};使用某排序算法按value排序后,结果为: {3,'D'}, {3,'B'}, {5,'A'}, {5,'C'} ,则这个排序算法是稳定的吗?
A. 稳定,因为相同 value 的元素相对顺序保持不变
B. 不稳定,因为 {3,'D'} 出现在 {3,'B'} 之前
C. 无法判断
D. 稳定,因为结果是有序的
解析:答案B。排序算法是否稳定,看同值排序时仍保持原次序的称稳定,否则称不稳定。由于按value排序,原{3,'B'}在{3,'D'}之前,{5,'A'}在{5,'C'}之前,稳定排序结果应该是{3,'B'},{3,'D'},{5,'A'},{5,'C'},但结果是{3,'D'}, {3,'B'}, {5,'A'}, {5,'C'},所以这个排序算法是不稳定的。故选B。
第11题 下面的函数 selectTopK() 实现从 n 个学生中选出前 k 名成绩最好的学生颁发奖学金(不需要对所有学生完全排序,只需要找出前 k 名),则横线上应填写( )。
struct Student { string name; int score; }; void selectTopK(Student students[], int n, int k) { for (int i = 0; i < k; i++) { int maxIdx = i; for (____________________) { // 在此处填入代码 if (students[j].score > students[maxIdx].score) { maxIdx = j; } } if (maxIdx != i) { Student temp = students[i]; students[i] = students[maxIdx]; students[maxIdx] = temp; } } }A. int j = 0; j < n; j++ B. int j = i + 1; j < n; j++ C. int j = i; j < n; j++ D. int j = 1; j <= n; j++
解析:答案B。程序的算法与选择排序类似:先取未排序区域n个数中的第1个数与后面n-1个进行比较,找到最大值,如最大值不是第1个则最大值与第1个数进行交换,这样最大值到了区域的第1个,再取第2个开始的区域,同样找区域中的最大,交换到第2个位置,以此类推,直到找到前k个最大值。所以循环变量j从i+1开始到n-1(下标从0开始),所以填 j=i+1; j<n,j++。故选B。
第12题 某游戏的排行榜系统需要实时更新玩家分数。每次只有一个玩家的分数发生变化,排行榜已经是按分数降序排列的。现在需要将更新后的玩家调整到正确位置。下面的函数 updateRanking() 要实现上述功能,则两处横线上应分别填写( )。
struct Player { string name; int score; }; // 玩家索引playerIdx的分数刚刚更新,需要调整位置 void updateRanking(Player players[], int size, int playerIdx) { Player updatedPlayer = players[playerIdx]; if (playerIdx > 0 && updatedPlayer.score > players[playerIdx - 1].score) { int i = playerIdx; while (____________________) { // 在此处填入代码 players[i] = players[i - 1]; i--; } players[i] = updatedPlayer; } else if (playerIdx < size - 1 && updatedPlayer.score < players[playerIdx + 1].score) { int i = playerIdx; while (____________________) { // 在此处填入代码 players[i] = players[i + 1]; i++; } players[i] = updatedPlayer; } }A.
i > 0 && updatedPlayer.score > players[i - 1].score
i < size - 1 && updatedPlayer.score < players[i + 1].score
B.
i < size - 1 && updatedPlayer.score < players[i + 1].score
i > 0 && updatedPlayer.score > players[i - 1].score
C.
i > 0 && updatedPlayer.score < players[i - 1].score
i < size - 1 && updatedPlayer.score < players[i + 1].score
D.
i > 0 && updatedPlayer.score < players[i - 1].score
i < size - 1 && updatedPlayer.score > players[i + 1].score
解析:答案A。程序的第10行判指定位置(playerIdx)的分数比上一位(playerIdx-1)高,则从i从playerIdx开始向上找直到0(逆序最大值位置),比较与上一位的分数,如仍大于则继续循环。所以i>0(i-1>=0),和updatedPlayer.score > players[i - 1].score同时成立,否则向后比较,比较与下一位的分数,如仍小于则继续循环。i<size-1(i+1<= size-1),和updatedPlayer.score < players[i + 1].score同时成立。故选A。
第13题 给定如下算法,其时间复杂度为( )。
bool f(int arr[], int n, int target) { for (int i = 0; i < n; i++) { int sum = 0; for (int j = 0; j < n; j++) { if (i & (1 << j)) { sum += arr[j]; } } if (sum == target) return true; } return false; }A. 𝑂(𝑛) B. 𝑂(𝑛²) C. 𝑂(𝑛³) D. 𝑂(2ⁿ)
解析:答案B。双重循环,循环次数都是n,所以时间复杂度为𝑂(𝑛²)。故选B。
第14题 执行下面 C++ 程序,会输出( )。
int main() { ofstream fout("test.txt"); fout << "Happy" << endl; fout << "New Year"; fout.close(); ifstream fin("test.txt"); string s1, s2; fin >> s1; getline(fin, s2); fin.close(); cout << s1 << "|" << s2; return 0; }A. Happy|New Year B. Happy| New Year C. HappyNew Year| D. Happy|
解析:答案D。第4行写文件时加了换行(endl),所以写到文件为两行,第一行Happy,第二行NewYear。第10行读取时,fin >> s1使用流提取操作符,按空白字符(空格、换行、制表符)分割输入,读取连续非空白字符并存储到string对象 s1 中,会残留第一行的换行符。getline(fin, s2) 读取整行输入,包括空格,直至遇到换行符(\n),并将换行符从流中移除,结果存储到 s2。由于第11行读到的是换行('\n'),所以s2是空字符串。故选D。
第15题 执行下面C++代码,会输出( )。
int divide(int a, int b) { if(b == 0) throw "Division by zero"; return a / b; } int main() { int result = 0; try { result = divide(10, 0); cout << "A"; } catch(const char* msg) { cout << "B"; result = -1; } cout << result; return 0; }A. A0 B. B-1 C. A10 D. 程序崩溃
解析:答案B。这是异常处理程序,调用divide(int a, int b)时,当b=0时抛出"Division by zero"异常。当主函数在try中运行result = divide(10, 0);时,因b=0会抛出异常,后面的cout << "A"不会被执行,招聘的异常要被catch子句接收处理,执行cout << "B",并给result赋-1,第16行输出result,所以输出结果为B-1。故选B。
2 判断题(每题 2 分,共 20 分)
第1题 小杨正在调试他的温度传感器程序,其中变量 x 保存当前温度。下面这段代码运行后,变量 x 的值变成 了 8 。
int x = 5; int *p = &x; *p = *p + 3;解析:答案√(正确)。p为指向x的指针,*p引用即x,*p+3,即x+3,所以执行*p = *p + 3;
后x=5+3,x变成8。故选正确。
第2题 一个结构体不能包含另一个结构体。
解析:答案╳(错误)。一个结构体可以包含另一个结构体。故错误。
第3题 在 C++ 中,定义如下二维数组: int a[3][4]; ,数组 a 在内存中是按行优先连续存放的,即a[0] [0]、a[0][1]、a[0][2]、a[0][3]在内存中是连续的。
解析:答案√(正确)。C++二维数组同行数据连续存放,行与行也是连续存放。故正确。
第4题 执行下面程序后,变量 a 的值会变成 15 。
void add(int &x){ x += 10; } int a = 5; add(a);解析:答案√(正确)。函数add(int &x)为引用传递参数,实参a将地址传递形参x,对x的修改就是对a的修改,因此执行x += 10之后,x由5变为15,并与A同地址,x相当于是a的别名,a=15。故正确。
第5题 执行下面的C++代码,会输出 8 ,因为两个指针地址相差 8 个字节(假设 int 占 4 字节)。
int arr[5] = {1, 2, 3, 4, 5}; int* p1 = arr; int* p2 = arr + 2; cout << p2 - p1; // 输出结果解析:答案╳(错误)。C++一维数组,数组名即为数组的首地址,所以p1是指向arr的指针。arr+2为地址加,p2指向后2个下标,指针之差是同对象内的“距离”,以“元素个数”为单位,而不是字节p2-p1=2≠8,地址相差2。故错误。
第6题 考虑用如下递推方式计算斐波那契数列,时间复杂度是𝑂(𝑛)。
int n = 10; int f[20]; f[0] = 0; f[1] = 1; for (int i = 2; i <= n; i++) f[i] = f[i - 1] + f[i - 2];解析:答案√(正确)。程序只是单循环,时间复杂度为𝑂(𝑛)。故正确。
第7题 冒泡排序和插入排序都是稳定排序算法。
解析:答案√(正确)。冒泡排序和插入排序都是稳定排序。故正确。
第8题 下面这段代码实现了选择排序算法。
void sort(int a[], int n) { for (int i = 1; i < n; i++) { int x = a[i]; int j = i - 1; while (j >= 0 && a[j] > x) { a[j + 1] = a[j]; j--; } a[j + 1] = x; } }解析:答案╳(错误)。选择排序,涉及求最大值或最小值,程序中并没有。故错误。
第9题 下面代码可以正常编译并输出 10 。
#include <iostream> using namespace std; int calculate(int x, int y = 10); int main() { cout << calculate(5); // 调用1 return 0; } int calculate(int x, int y) { return x * y; } int calculate(int x) { // 重载函数 return x * 2; }解析:答案╳(错误)。第4行函数声明中声明双参数,其中y默认为10,calculate(5);调用的并未调重载函数,而是按默认参数,双参数调用,x=5,y=10,返回x*y=5*10=50。故错误。
第10题 执行下面代码会输出 100 。
int main() { ofstream fout("data.txt"); fout << 10 << " " << 20 << endl; fout << 30 << " " << 40; fout.close(); ifstream fin("data.txt"); int a, b, c, d; fin >> a >> b >> c >> d; fin.close(); cout << a + b + c + d; return 0; }解析:答案√(正确)。第3~4行向文件写了两行,第一行10 20换行,第二行30 40。fin会丢掉前缀空白字符,一直读到空白字符(不含空白字符)。a读到的是10,b读到的是20,c读到的是30,d读到的是40,所以结果为10+20+30+40=100。故正确。
3 编程题(每题 25 分,共 50 分)
3.1 编程题1
- 试题名称:建造
- 时间限制:1.0 s
- 内存限制:512.0 MB
3.1.1题目描述
小A有一张𝑀行𝑁列的地形图,其中第𝑖行第𝑗列的数字𝑎𝑖𝑗代表坐标 (𝑖, 𝑗) 的海拔高度。停机坪为一个3×3的区域且内部所有9个点的最大高度和最小高度之差不超过𝐻。
小A想请你计算出,在所有适合建造停机坪的区域中,区域内部9个点海拔之和最大是多少。
3.1.2 输入格式
第一行三个正整数𝑀, 𝑁, 𝐻,含义如题面所示。
之后𝑀行,第𝑖行包含𝑁个整数
,
, …,
,代表坐标 (𝑖, 𝑗) 的高度。
数据保证总存在一个适合建造停机坪的区域。
3.1.3 输出格式
输出一行,代表最大的海拔之和。
3.1.4 样例
3.1.4.1 输入样例
5 5 3 5 5 5 5 5 5 1 5 1 5 5 5 5 5 5 5 2 5 2 5 3 5 5 5 23.1.4.2 输出样例
403.1.5 数据范围
对于所有测试点,保证1≤𝑀, 𝑁≤10³, 1≤𝐻, 𝑎ᵢⱼ≤10⁵。
3.1.6 编写程序
编程思路:
题目要求寻找一个3×3的区域,其中的最高海拔与最低海拔之差不超过𝐻,且9个点的海拔之和最大。如图1所示,以样例为例,𝑀×𝑁的区域,选一3×3的区域,水平方向可移动𝑀-2次,垂直方向可移动𝑁-2次。只3×3的区域内的最高海拔与最低海拔之差不超过𝐻,就是一个有效区域,其海拔之和与当前最大海拔之和比较,两者大者作为当前最大海拔之和,最后输出即可。图1中黑色框中的9个海拔的最大海拔差为4>𝐻(=3),不合适;黄底紫色框中的9个海拔的最大海拔差也是4>𝐻,不合适;红色框中的9个海拔的最大海拔差也是3=𝐻,合适,但是否是最大海拔之和要验证。

图1 3.1题分析用图
方法一:枚举法,枚举3×3的区域的左上角坐标,求以此点为左上角的3×3的区域中的各点海拔和、最高海拔、最低海拔。符合最高、最低海拔差有区域求最大海拔和。
参考程序代码如下:
#include <iostream> using namespace std; int a[1005][1005]; // 𝑀, 𝑁≤10³ int main() { int M, N, H; long long maxs = 0; // maxs为9个点的最大海拔和 cin >> M >> N >> H; for (int i = 0; i < M; i++) for (int j = 0; j < N; j++) cin >> a[i][j]; // 𝑎ᵢⱼ≤10⁵ for (int i = 0; i < M - 2; i++) for (int j = 0; j < N - 2; j++) { long long locs = 0; // 本区域海拔和,10³×10³个10⁵数的和为10¹¹级超过int int l_max = a[i][j], l_min = a[i][j]; // 区域最高、最低海拔,赋当前点海拔 for (int x = 0; x < 3; x++) for (int y = 0; y < 3; y++) { locs += a[i + x][j + y]; l_max = l_max > a[i + x][j + y] ? l_max : a[i + x][j + y]; l_min = l_min < a[i + x][j + y] ? l_min : a[i + x][j + y]; } if (l_max - l_min <= H) maxs = maxs > locs ? maxs : locs; } cout << maxs; return 0; }方法二:
算法相同,3×3区域的另一种表示,求最大、最小的另一种写法,程序更简洁一些。程序代码如下:
#include <iostream> using namespace std; int a[1005][1005]; // 𝑀, 𝑁≤10³ int main() { int M, N, H; long long maxs = 0; // maxs为9个点的最大海拔和 cin >> M >> N >> H; for (int i = 0; i < M; i++) for (int j = 0; j < N; j++) cin >> a[i][j]; // 𝑎ᵢⱼ≤10⁵ for (int i = 0; i < M - 2; i++) for (int j = 0; j < N - 2; j++) { long long locs = 0; // 本区域海拔和,10³×10³个10⁵数的和为10¹¹级超过int int l_max = a[i][j], l_min = a[i][j]; // 区域最高、最低海拔,赋当前点海拔 for (int x = i; x < i + 3; x++) for (int y = j; y < j + 3; y++) { locs += a[x][y]; if (a[x][y] > l_max) l_max = a[x][y]; if (a[x][y] < l_min) l_min = a[x][y]; } if (l_max - l_min <= H) if (locs > maxs)maxs = locs; } cout << maxs; return 0; }3.2 编程题2
- 试题名称:优先购买
- 时间限制:1.0 s
- 内存限制:512.0 MB
3.2.1题目描述
小A有𝑀元预算。商店有𝑁个商品,每个商品有商品名𝑆、价格𝑃和优先级𝑉三种属性,其中𝑉为正整数,且越小代表商品的优先级越高。 小A的购物策略为:
总是优先买优先级最高的东西;
如果有多个最高优先级商品,购买价格最低的;
如果有多个优先级最高且价格最低的商品,购买商品名字典序最小的。
小A想知道能购买哪些商品。
3.2.2 输入格式
第一行两个正整数𝑀, 𝑁,代表预算和商品数。
之后𝑁行,每行一个商品,依次为𝑆ᵢ𝑃ᵢ𝑉ᵢ,代表第𝑖个商品的商品名、价格、优先级。
数据保证不存在两个名字相同的商品。
3.2.3 输出格式
按照字典序从小到大的顺序,输出所有购买商品的商品名。
3.2.4 样例
3.2.4.1 输入样例
20 4 apple 6 8 bus 15 1 cab 1 10 water 4 83.2.4.2 输出样例
bus cab water3.2.5 数据范围
对于所有测试点,保证1≤|𝑆ᵢ|≤10, 1≤𝑀, 𝑃ᵢ≤10⁵, 1≤𝑁≤10³, 1≤𝑉ᵢ≤10。商品名仅由小写字母组成且不存在两个相同的商品名。
3.2.6 参考程序
编程思路:
排序确保了购物策略的正确性(先按优先级排(升序),同优先级按价格排(升序),优先级、同价格按商品名排(升序,即字典序)),贪心选择在预算允许下尽可能购买商品,最终输出按字典序排列输出。排序用STL中的sort()函数。
方法一:
用结构体存储M个商品和购买商品的商品名称。参考程序代码如下:
#include <iostream> #include <algorithm> using namespace std; const int N = 1005; // 最大商品数量 struct Node { // 定义商品结构体 string s; // 商品名称 int p, v; // 商品价格和优先级 } a[N], b[N]; // 存储所有商品和购买的商品 int m, n, cur;// m: 预算, n: 商品总数, cur:已购买商品数量 bool cmp(Node x, Node y) { // 排序次序:v(优先级)升序 → p(价格)升序 → s(名称)字典序 if (x.v != y.v) return x.v < y.v; // 先按优先级升序排序 if (x.p != y.p) return x.p < y.p; // 优先级相同,按价格升序 return x.s < y.s; // 优先级和价格都相同,按商品名字典序 } int main() { cin >> m >> n; // 输入预算m和商品数量n for (int i = 0; i < n; i++) // 输入n个商品信息 cin >> a[i].s >> a[i].p >> a[i].v; sort(a, a + n, cmp); // 排序,规则先按v升序,v相同按p升序,v、p都相同按s字典序 for (int i = 0; i < n; i++) { //在预算范围内尽可能多地购买商品 if (m >= a[i].p) { // 预算足够 m -= a[i].p; // 扣除价格 b[cur++] = a[i]; // 将商品加入购买列表 } } sort(b, b + cur, [](const Node& a, const Node& b) { return a.s < b.s; // 对购买的商品按名称字典序排序 }); for (int i = 0; i < cur; i++) { // 输出购买的商品名称 cout << b[i].s << endl; } return 0; }方法二:
由于输出只需输出购买商品的商品名称,为简化排序,购买商品的商品名称用字符串数组进行存储,M个商品仍用结构体存储。
#include <iostream> #include <string> #include <algorithm> using namespace std; const int N = 1005; // 最大商品数量 struct Node { // 定义商品结构体 string s; // 商品名称 int p, v; // 商品价格和优先级 } a[N];// 存储所有商品 string b[N]; // 存储最终成功购买的商品名称 int m, n, cur;// m: 预算, n: 商品总, cur:已购买商品数量 bool cmp(Node x, Node y) { // 排序次序:v(优先级)升序 → p(价格)升序 → s(名称)字典序 if (x.v != y.v) return x.v < y.v; // 先按优先级升序排序 if (x.p != y.p) return x.p < y.p; // 优先级相同,按价格升序 return x.s < y.s;// 优先级和价格都相同,按商品名字典序 } int main() { cin >> m >> n; // 输入预算m和商品数量n for (int i = 0; i < n; i++) // 输入n个商品信息 cin >> a[i].s >> a[i].p >> a[i].v; sort(a, a + n, cmp); // 排序,规则先按v升序,v相同按p升序,v、p都相同按s字典序 for (int i = 0; i < n; i++) { //在预算范围内尽可能多地购买商品 if (m >= a[i].p) { // 预算足够 m -= a[i].p; // 扣除价格 b[cur++] = a[i].s; // 将商品名称加入购买列表 } } sort(b, b + cur); // 对购买的商品按名称字典序排序 for (int i = 0; i < cur; i++) {// 输出购买的商品名称 cout << b[i] << endl; } return 0; }