2021年12月 C/C++(五级)真题解析#中国电子学会#全国青少年软件编程等级考试

在这里插入图片描述

第1题:书架

John最近买了一个书架用来存放奶牛养殖书籍,但书架很快被存满了,只剩最顶层有空余。
John共有N头奶牛(1 ≤ N ≤ 20,000),每头奶牛有自己的高度Hi(1 ≤ Hi ≤ 10,000),N头奶牛的总高度为S。书架高度为B(1 ≤ B ≤ S < 2,000,000,007).
为了到达书架顶层,奶牛可以踩着其他奶牛的背,像叠罗汉一样,直到他们的总高度不低于书架高度。当然若奶牛越多则危险性越大。为了帮助John到达书架顶层,找出使用奶牛数目最少的解决方案吧。
时间限制:10000
内存限制:65536
输入
第1行:空格隔开的整数N和B 第2~N+1行:第i+1行为整数Hi
输出
能达到书架高度所使用奶牛的最少数目
样例输入
6 40
6
18
11
13
19
11
样例输出
3

以下是使用贪心算法来解决书架问题的C语言代码:

#include <stdio.h>
#include <stdlib.h>#define MAX_N 20000int compare(const void* a, const void* b) {return *(int*)a - *(int*)b;
}int minCows(int heights[MAX_N], int n, int b) {qsort(heights, n, sizeof(int), compare);  // 将奶牛的高度排序int sum = 0;int count = 0;for (int i = n - 1; i >= 0; i--) {sum += heights[i];count++;if (sum >= b) {break;}}return count;
}int main() {int n, b;int heights[MAX_N];// 读取输入scanf("%d %d", &n, &b);for (int i = 0; i < n; i++) {scanf("%d", &heights[i]);}// 使用贪心算法求解最少使用的奶牛数目int minCowsCount = minCows(heights, n, b);// 输出结果printf("%d\n", minCowsCount);return 0;
}

该算法使用贪心算法的思想,通过将奶牛的高度进行排序,并从最高的奶牛开始,逐个累加奶牛的高度,直到总高度不低于书架高度B为止。首先,使用快速排序算法对奶牛的高度进行排序。然后,从最高的奶牛开始累加其高度,并记录使用的奶牛数目。如果累加的总高度不低于书架高度B,则停止累加。最后,返回使用的奶牛数目作为答案。

第2题:棋盘问题

在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。
时间限制:1000
内存限制:65536
输入
输入含有多组测试数据。 每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n 当为-1 -1时表示输入结束。 随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。
输出
对于每一组数据,给出一行输出,输出摆放的方案数目C (数据保证C<2^31)。
样例输入
2 1
#.
.#
4 4
…#
…#.
.#…
#…
-1 -1
样例输出
2
1

以下是使用回溯法来解决棋盘问题的C语言代码:

#include <stdio.h>
#include <stdbool.h>#define MAX_N 8int count = 0;  // 记录可行的摆放方案数bool isValid(char board[MAX_N][MAX_N], int row, int col, int n) {// 检查同一行是否已经有棋子for (int c = 0; c < col; c++) {if (board[row][c] == 'Q') {return false;}}// 检查左上方对角线是否已经有棋子for (int r = row, c = col; r >= 0 && c >= 0; r--, c--) {if (board[r][c] == 'Q') {return false;}}// 检查左下方对角线是否已经有棋子for (int r = row, c = col; r < n && c >= 0; r++, c--) {if (board[r][c] == 'Q') {return false;}}return true;
}void backtrack(char board[MAX_N][MAX_N], int col, int n, int k) {if (col == n) {if (k == 0) {count++;}return;}for (int row = 0; row < n; row++) {if (board[row][col] == '#' && isValid(board, row, col, n)) {board[row][col] = 'Q';backtrack(board, col + 1, n, k - 1);board[row][col] = '#';}}backtrack(board, col + 1, n, k);
}int chessboard(int n, int k, char board[MAX_N][MAX_N]) {count = 0;backtrack(board, 0, n, k);return count;
}int main() {int n, k;char board[MAX_N][MAX_N];while (scanf("%d %d", &n, &k) == 2) {if (n == -1 && k == -1) {break;}for (int i = 0; i < n; i++) {scanf("%s", board[i]);}int result = chessboard(n, k, board);printf("%d\n", result);}return 0;
}

该算法使用回溯法的思想,通过递归地尝试在每个位置放置棋子,同时检查放置的位置是否满足要求。首先,定义isValid函数用于检查某个位置是否合法,即同一行、同一列以及对角线上没有其他棋子。然后,使用backtrack函数进行回溯搜索,从左到右、从上到下依次尝试在每个位置放置棋子。如果当前位置合法,就将棋子放置在该位置,并继续在下一列进行回溯搜索。如果当前位置不合法,则继续在下一行尝试。当回溯到最后一列时,如果已经放置了k个棋子,则找到了一个可行的摆放方案,将计数器加1。最后,调用chessboard函数进行求解,并输出可行的摆放方案数目C。

第3题:课程表

现在你总共有n门课需要选,记为0到n-1。在选修某些课程之前需要一些先修课程。例如,想要学习课程0,你需要先完成课程1,我们用一个匹配来表示他们:[0, 1]。给定课程总量以及它们的先决条件,判断是否可能完成所有课程的学习?
时间限制:1000
内存限制:65536
输入
多组数据。每组数据第一行是n和m,n表示有n门课程,m表示有m组依赖关系,接下来的m行是依赖关系的具体信息a b,表示第a门课程依赖第b门课程。 0<=n <=1000,0 <= m <= 4000 两组数据之间可能有空行
输出
对每组数据,能完成输出 True,不能完成输出 False
样例输入
2 1
1 0
2 2
1 0
0 1
样例输出
True
False
提示
示例2解释: 总共有2门课程。学习课程1之前,你需要先完成课程0;并且学习课程0之前,你还应先完成课程1。这是不可能的。

对于课程表问题,使用搜索剪枝技术是一个有效的方法。我们可以使用深度优先搜索(DFS)来遍历课程的依赖关系,并在搜索过程中进行剪枝以提高效率。

以下是使用搜索剪枝技术来解决课程表问题的C语言代码:

#include <stdio.h>
#include <stdbool.h>#define MAX_N 1000
#define MAX_M 4000bool dfs(int course, int numCourses, int prerequisites[MAX_M][2], int numPrerequisites, bool visited[MAX_N], bool path[MAX_N]) {visited[course] = true;  // 标记当前课程为已访问path[course] = true;  // 将当前课程加入遍历路径中// 遍历当前课程的后续课程for (int i = 0; i < numPrerequisites; i++) {if (prerequisites[i][1] == course) {int nextCourse = prerequisites[i][0];// 判断是否存在环路,即当前课程在当前的遍历路径中if (path[nextCourse]) {return false;}// 如果后续课程未访问,则继续进行深度优先搜索if (!visited[nextCourse]) {if (!dfs(nextCourse, numCourses, prerequisites, numPrerequisites, visited, path)) {return false;}}}}path[course] = false;  // 将当前课程从遍历路径中移除return true;
}bool canFinish(int numCourses, int prerequisites[MAX_M][2], int numPrerequisites) {bool visited[MAX_N] = {false};  // 记录课程是否已访问bool path[MAX_N] = {false};  // 记录当前的遍历路径// 对每门课程进行深度优先搜索for (int i = 0; i < numCourses; i++) {if (!visited[i]) {if (!dfs(i, numCourses, prerequisites, numPrerequisites, visited, path)) {return false;}}}return true;
}int main() {int numCourses, numPrerequisites;int prerequisites[MAX_M][2];while (scanf("%d %d", &numCourses, &numPrerequisites) == 2) {if (numCourses == 0 && numPrerequisites == 0) {break;}for (int i = 0; i < numPrerequisites; i++) {scanf("%d %d", &prerequisites[i][0], &prerequisites[i][1]);}bool result = canFinish(numCourses, prerequisites, numPrerequisites);printf("%s\n", result ? "True" : "False");}return 0;
}

该算法使用深度优先搜索(DFS)进行遍历,通过递归地搜索课程的依赖关系。首先,定义dfs函数进行深度优先搜索,其中course表示当前的课程,visited用于记录课程是否已访问,path用于记录当前的遍历路径。在搜索过程中,首先将当前课程标记为已访问,并将其加入遍历路径中。然后,遍历当前课程的后续课程,如果发现后续课程已经在当前的遍历路径中,则表示存在环路,返回false。如果后续课程未访问,则继续进行深度优先搜索。最后,将当前课程从遍历路径中移除,并返回true表示搜索完成。在canFinish函数中,对每门课程进行深度优先搜索,如果存在环路,则返回false;如果所有课程都能够完成搜索,返回true。最后,调用canFinish函数进行求解,并输出结果。

第4题:拯救公主

多灾多难的公主又被大魔王抓走啦!国王派遣了第一勇士阿福去拯救她。
身为超级厉害的术士,同时也是阿福的好伙伴,你决定祝他一臂之力。你为阿福提供了一张大魔王根据地的地图,上面标记了阿福和公主所在的位置,以及一些不能够踏入的禁区。你还贴心地为阿福制造了一些传送门,通过一个传送门可以瞬间转移到任意一个传送门,当然阿福也可以选择不通过传送门瞬移。传送门的位置也被标记在了地图上。此外,你还查探到公主所在的地方被设下了结界,需要集齐K种宝石才能打开。当然,你在地图上也标记出了不同宝石所在的位置。
你希望阿福能够带着公主早日凯旋。于是在阿福出发之前,你还需要为阿福计算出他最快救出公主的时间。
地图用一个R×C的字符矩阵来表示。字符S表示阿福所在的位置,字符E表示公主所在的位置,字符#表示不能踏入的禁区,字符$表示传送门,字符.表示该位置安全,数字字符0至4表示了宝石的类型。阿福每次可以从当前的位置走到他上下左右四个方向上的任意一个位置,但不能走出地图边界。阿福每走一步需要花费1个单位时间,从一个传送门到达另一个传送门不需要花费时间。当阿福走到宝石所在的位置时,就视为得到了该宝石,不需要花费额外时间。
时间限制:1000
内存限制:65536
输入
第一行是一个正整数T(1 <= T <= 10),表示一共有T组数据。 每一组数据的第一行包含了三个用空格分开的正整数R、C(2 <= R, C <= 200)和K,表示地图是一个R×C的矩阵,而阿福需要集齐K种宝石才能够打开拘禁公主的结界。 接下来的R行描述了地图的具体内容,每一行包含了C个字符。字符含义如题目描述中所述。保证有且仅有一个S和E。$的数量不超过10个。宝石的类型在数字0至4范围内,即不会超过5种宝石。
输出
对于每一组数据,输出阿福救出公主所花费的最少单位时间。若阿福无法救出公主,则输出“oop!”(只输出引号里面的内容,不输出引号)。每组数据的输出结果占一行。
样例输入
1
7 8 2

…S…#0.
.##…1…
.0#…
…1#…
…##E…
…1…
样例输出
11

根据题目要求,我们可以使用贪心算法来解决这个问题。贪心算法的思想是每一步都选择当前最优的解决方案,希望最终能够得到全局最优解。

下面是使用贪心算法解决该问题的C语言代码示例:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define MAX_ROWS 200
#define MAX_COLS 200int minTime; // 最少单位时间
int gemsCollected; // 已经收集到的宝石数量
char map[MAX_ROWS][MAX_COLS];
int visited[MAX_ROWS][MAX_COLS];
int rows, cols, requiredGems;
int startRow, startCol, endRow, endCol; // 起始位置和目标位置的行列坐标
int gems[MAX_ROWS][MAX_COLS]; // 记录宝石的类型// 计算两点之间的曼哈顿距离
int manhattanDistance(int row1, int col1, int row2, int col2) {return abs(row1 - row2) + abs(col1 - col2);
}// 贪心算法
void greedy(int row, int col, int time) {// 边界条件判断if (row < 0 || row >= rows || col < 0 || col >= cols || visited[row][col] || map[row][col] == '#')return;// 标记当前位置为已访问visited[row][col] = 1;// 到达目标位置,更新最少单位时间if (row == endRow && col == endCol) {if (gemsCollected == requiredGems) {if (time < minTime || minTime == -1)minTime = time;}visited[row][col] = 0; // 恢复当前位置为未访问状态return;}// 如果当前位置是宝石,则增加宝石数量if (gems[row][col] != -1)gemsCollected++;// 向四个方向进行搜索greedy(row - 1, col, time + 1); // 上greedy(row + 1, col, time + 1); // 下greedy(row, col - 1, time + 1); // 左greedy(row, col + 1, time + 1); // 右// 如果当前位置是宝石,则减少宝石数量if (gems[row][col] != -1)gemsCollected--;// 恢复当前位置为未访问状态visited[row][col] = 0;
}int main() {int numCases;scanf("%d", &numCases);while (numCases--) {scanf("%d %d %d", &rows, &cols, &requiredGems);// 初始化minTime = -1;gemsCollected = 0;// 读取地图数据for (int i = 0; i < rows; i++) {scanf("%s", map[i]);for (int j = 0; j < cols; j++) {visited[i][j] = 0;if (map[i][j] == 'S') {startRow = i;startCol = j;} else if (map[i][j] == 'E') {endRow = i;endCol = j;} else if (map[i][j] >= '0' && map[i][j] <= '4') {gems[i][j] = map[i][j] - '0';} else {gems[i][j] = -1;}}}// 计算起始位置到每个宝石的曼哈顿距离int gemDistances[5];memset(gemDistances, 0, sizeof(gemDistances));for (int i = 0; i < rows; i++) {for (int j = 0; j < cols; j++) {if (gems[i][j] != -1) {int distance = manhattanDistance(startRow, startCol, i, j);if (gemDistances[gems[i][j]] == 0 || distance < gemDistances[gems[i][j]]) {gemDistances[gems[i][j]] = distance;}}}}// 根据宝石的曼哈顿距离进行排序for (int i = 0; i < requiredGems; i++) {int minDistance = -1;int minGem = -1;for (int j = 0; j < 5; j++) {if (gemDistances[j] != 0 && (minDistance == -1 || gemDistances[j] < minDistance)) {minDistance = gemDistances[j];minGem = j;}}gemDistances[minGem] = 0;for (int j = 0; j < rows; j++) {for (int k = 0; k < cols; k++) {if (gems[j][k] == minGem) {gems[j][k] = i;}}}}// 使用贪心算法搜索最短路径greedy(startRow, startCol, 0);// 输出结果if (minTime != -1) {printf("%d\n", minTime);} else {printf("oop!\n");}}return 0;
}

这个代码使用了深度优先搜索和贪心算法来解决问题,首先计算起始位置到每个宝石的曼哈顿距离,然后按照宝石的距离进行排序,然后使用贪心算法进行搜索,直到达到目标位置并且收集到足够数量的宝石。如果无法救出公主,则输出"oop!"。

请注意,这只是一个示例代码,可能还有一些边界情况没有考虑到,你可以根据实际情况进行修改和优化。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/89654.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Spring Boot 的 Ext JS 应用框架之coworkee

Ext JS 官方提供了一个人员管理的完整应用框架 - coworkee。该框架的显示如下: 该框架的布局特点如下: 布局方式: 左右布局, 左侧导航栏默认收合特点:左侧导航区占用空间小, 工作区较大, 适合没有二级导航栏,工作区需要显示的内容较多的系统。如果导航栏是横向底部,就…

AI 绘画Stable Diffusion 研究(十七)SD lora 详解(上)

大家好&#xff0c;我是风雨无阻。 本期内容&#xff1a; Lora的原理是什么&#xff1f;Lora如何下载安装&#xff1f;Lora如何使用&#xff1f; 大家还记得 AI 绘画Stable Diffusion 研究&#xff08;三&#xff09;sd模型种类介绍及安装使用详解 这篇文章中&#xff0c;曾简…

2023蓝帽杯初赛ctf部分题目

Web LovePHP 打开网站环境&#xff0c;发现显示出源码 来可以看到php版本是7.4.33 简单分析了下&#xff0c;主要是道反序列化的题其中发现get传入的参数里有_号是非法字符&#xff0c;如果直接传值传入my_secret.flag&#xff0c;会被php处理掉 绕过 _ 的方法 对于__可以…

Ubuntu断电重启后黑屏左上角光标闪烁,分辨率低解决办法,ubuntu系统display只有4:3 怎么办?太卡

这个问题主要是显卡驱动问题&#xff0c;按照步骤更新显卡驱动 1&#xff0c;选择metapackage 并且选择proprietary版本&#xff0c;选择版本号选择最新的版本。 2&#xff0c;具体步骤参考 前言 笔者在安装显卡驱动时并未遇到问题&#xff0c;主要是后续屏幕亮度无法调节&…

力扣141. 环形链表

141. 环形链表 简单 2K 相关企业 给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评测系统内部使用整数 pos 来表示链…

OK3588应用之——人脸和人脸关键点的检测(十四)

一、主机模型转换 采用FastDeploy来部署应用深度学习模型到OK3588板卡上 进入主机Ubuntu的虚拟环境 conda activate ok3588 主机环境搭建可以参考上一篇 《OK3588板卡实现人像抠图&#xff08;十二&#xff09;》 转换成RKNN模型 cd FastDeploy wget https://bj.bcebos.co…

ssm+vue毕业论文管理系统源码和论文

ssmvue毕业论文管理系统053 开发工具&#xff1a;idea 数据库mysql5.7 数据库链接工具&#xff1a;navcat,小海豚等 技术&#xff1a;ssm 摘 要 高校规模越来越大&#xff0c;学生越来越多&#xff0c;每年都有大批的大学生完成学业。毕业之前&#xff0c;各大高校设立…

小企业需不需要内部知识库?为什么都在倡导内部知识沉淀?

有多种方法可以提高员工敬业度和员工工作效率&#xff0c;从给予信任到创造积极的工作环境。但一还有一个不为人知但十分有效的方式——为员工创建良好的内部知识库。所以小企业同样需要内部知识库&#xff0c;以下是为什么倡导内部知识沉淀的理由&#xff1a; 知识积累与传承…

Unity插件---Dotween

1.什么是DOTween DoTween 是由 Demigiant 开发的&#xff0c;被广泛应用于 Unity 游戏开发中。它是一个流行的动画插件&#xff0c;被许多开发者用于创建流畅、高效的动画效果&#xff0c;提升游戏体验。 2.DOTween的初始配置 ①set up 首先找到DOTween Unity Panel 的面板 点…

算法:模拟思想算法

文章目录 实现原理算法思路典型例题替换所有问号提莫攻击N字型变换外观序列 总结 本篇总结的是模拟算法 实现原理 模拟算法的实现原理很简单&#xff0c;就是依据题意实现题意的目的即可&#xff0c;考察的是你能不能实现题目题意的代码能力 算法思路 没有很明显的算法思路…

MySQL—MySQL主从如何保证强一致性

一、前言 涉及到的东西&#xff1a;两阶段提交&#xff0c;binlog三种格式 1、两阶段提交 在持久化 redo log 和 binlog 这两份日志的时候&#xff0c;如果出现半成功的状态&#xff0c;就会造成主从环境的数据不一致性。这是因为 redo log 影响主库的数据&#xff0c;binlog…

递归算法学习——子集

目录 一&#xff0c;题目解析 二&#xff0c;例子 三&#xff0c;题目接口 四&#xff0c;解题思路以及代码 1.完全深度搜索 2.广度搜索加上深度优先搜索 五&#xff0c;相似题 1.题目 2.题目接口 3.解题代码 一&#xff0c;题目解析 给你一个整数数组 nums &#xff0c…