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

在这里插入图片描述

C/C++编程(1~8级)全部真题・点这里

第1题:走出迷宫

当你站在一个迷宫里的时候,往往会被错综复杂的道路弄得失去方向感,如果你能得到迷宫地图,事情就会变得非常简单。
假设你已经得到了一个n*m的迷宫的图纸,请你找出从起点到出口的最短路。
时间限制:1000
内存限制:65536
输入
第一行是两个整数n和m(1<=n,m<=100),表示迷宫的行数和列数。 接下来n行,每行一个长为m的字符串,表示整个迷宫的布局。字符’.‘表示空地,’#'表示墙,'S’表示起点,'T’表示出口。
输出
输出从起点到出口最少需要走的步数。
样例输入
3 3
S#T
.#.

样例输出
6

以下是一个使用C语言编写的解决方案:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define MAX_SIZE 100typedef struct {int x;int y;
} Point;typedef struct {Point point;int distance;
} QueueNode;typedef struct {QueueNode data[MAX_SIZE];int front;int rear;
} Queue;void initQueue(Queue *queue) {queue->front = 0;queue->rear = 0;
}int isQueueEmpty(Queue *queue) {return queue->front == queue->rear;
}int isQueueFull(Queue *queue) {return (queue->rear + 1) % MAX_SIZE == queue->front;
}void enqueue(Queue *queue, QueueNode node) {if (isQueueFull(queue)) {printf("Error: Queue is full.\n");return;}queue->data[queue->rear] = node;queue->rear = (queue->rear + 1) % MAX_SIZE;
}QueueNode dequeue(Queue *queue) {if (isQueueEmpty(queue)) {printf("Error: Queue is empty.\n");QueueNode emptyNode = {{-1, -1}, -1};return emptyNode;}QueueNode node = queue->data[queue->front];queue->front = (queue->front + 1) % MAX_SIZE;return node;
}int isValid(int x, int y, int n, int m) {return x >= 0 && x < n && y >= 0 && y < m;
}int shortestPath(char maze[][MAX_SIZE], int n, int m, Point start, Point end) {int dx[] = {-1, 1, 0, 0};int dy[] = {0, 0, -1, 1};Queue queue;initQueue(&queue);int visited[MAX_SIZE][MAX_SIZE] = {0};visited[start.x][start.y] = 1;QueueNode startNode = {start, 0};enqueue(&queue, startNode);while (!isQueueEmpty(&queue)) {QueueNode currentNode = dequeue(&queue);Point currentPoint = currentNode.point;int currentDistance = currentNode.distance;if (currentPoint.x == end.x && currentPoint.y == end.y) {return currentDistance;}for (int i = 0; i < 4; i++) {int newX = currentPoint.x + dx[i];int newY = currentPoint.y + dy[i];if (isValid(newX, newY, n, m) && maze[newX][newY] != '#' && !visited[newX][newY]) {visited[newX][newY] = 1;Point newPoint = {newX, newY};QueueNode newNode = {newPoint, currentDistance + 1};enqueue(&queue, newNode);}}}return -1; // 没有找到路径
}int main() {int n, m;scanf("%d %d", &n, &m);char maze[MAX_SIZE][MAX_SIZE];Point start, end;for (int i = 0; i < n; i++) {scanf("%s", maze[i]);for (int j = 0; j < m; j++) {if (maze[i][j] == 'S') {start.x = i;start.y = j;} else if (maze[i][j] == 'T') {end.x = i;end.y = j;}}}int shortestDistance = shortestPath(maze, n, m, start, end);printf("%d\n", shortestDistance);return 0;
}

在给定的示例输入下,该程序将产生以下输出:

6

该程序使用广度优先搜索(BFS)算法来找到从起点到出口的最短路径。它使用一个队列来保存待处理的节点,并使用一个二维数组来记录已访问的位置。

程序首先读取迷宫的行数和列数,然后读取迷宫的布局。通过遍历迷宫,找到起点和出口的位置。

接下来,程序使用BFS算法来搜索最短路径。它从起点开始,将起点入队,并将起点标记为已访问。然后,它进入一个循环,直到队列为空。请注意,在使用这个解决方案时,输入的迷宫地图必须符合以下要求:

  • 'S’表示起点,只能有一个。

  • 'T’表示出口,只能有一个。

  • '#'表示墙。

  • '.'表示空地。

此外,该程序假设迷宫是连通的,即从起点到出口存在至少一条路径。如果迷宫是不连通的,或者不存在从起点到出口的路径,程序将返回-1。

第2题:拯救公主

多灾多难的公主又被大魔王抓走啦!国王派遣了第一勇士阿福去拯救她。
身为超级厉害的术士,同时也是阿福的好伙伴,你决定祝他一臂之力。你为阿福提供了一张大魔王根据地的地图,上面标记了阿福和公主所在的位置,以及一些不能够踏入的禁区。你还贴心地为阿福制造了一些传送门,通过一个传送门可以瞬间转移到任意一个传送门,当然阿福也可以选择不通过传送门瞬移。传送门的位置也被标记在了地图上。此外,你还查探到公主所在的地方被设下了结界,需要集齐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_SIZE 200
#define INF 999999typedef struct {int x;int y;
} Point;typedef struct {Point point;int distance;
} QueueNode;typedef struct {QueueNode data[MAX_SIZE * MAX_SIZE];int front;int rear;
} Queue;void initQueue(Queue *queue) {queue->front = 0;queue->rear = 0;
}int isQueueEmpty(Queue *queue) {return queue->front == queue->rear;
}int isQueueFull(Queue *queue) {return (queue->rear + 1) % (MAX_SIZE * MAX_SIZE) == queue->front;
}void enqueue(Queue *queue, QueueNode node) {if (isQueueFull(queue)) {printf("Error: Queue is full.\n");return;}queue->data[queue->rear] = node;queue->rear = (queue->rear + 1) % (MAX_SIZE * MAX_SIZE);
}QueueNode dequeue(Queue *queue) {if (isQueueEmpty(queue)) {printf("Error: Queue is empty.\n");QueueNode emptyNode = {{-1, -1}, -1};return emptyNode;}QueueNode node = queue->data[queue->front];queue->front = (queue->front + 1) % (MAX_SIZE * MAX_SIZE);return node;
}int isValid(int x, int y, int r, int c) {return x >= 0 && x < r && y >= 0 && y < c;
}int shortestRescueTime(char map[][MAX_SIZE], int r, int c, int k, Point start, Point end) {int dx[] = {-1, 1, 0, 0};int dy[] = {0, 0, -1, 1};Queue queue;initQueue(&queue);int visited[MAX_SIZE][MAX_SIZE][1 << 5] = {0};visited[start.x][start.y][0] = 1;QueueNode startNode = {start, 0};enqueue(&queue, startNode);while (!isQueueEmpty(&queue)) {QueueNode currentNode = dequeue(&queue);Point currentPoint = currentNode.point;int currentDistance = currentNode.distance;if (currentPoint.x == end.x && currentPoint.y == end.y) {return currentDistance;}for (int i = 0; i < 4; i++) {int newX = currentPoint.x + dx[i];int newY = currentPoint.y + dy[i];if (isValid(newX, newY, r, c) && map[newX][newY] != '#' && !visited[newX][newY][0]) {int newMask = 0;if (map[newX][newY] >= '0' && map[newX][newY] <= '4') {int gemType = map[newX][newY] - '0';newMask = (1 << gemType);}for (int j = 0; j < (1 << k); j++) {int nextMask = j | newMask;if (!visited[newX][newY][nextMask]) {visited[newX][newY][nextMask] = 1;Point newPoint = {newX, newY};QueueNode newNode = {newPoint, currentDistance + 1};enqueue(&queue, newNode);}}}}}return -1; // 无法救出公主
}int main() {int t;scanf("%d", &t);while (t--) {int r, c, k;scanf("%d %d %d", &r, &c, &k);char map[MAX_SIZE][MAX_SIZE];Point start, end;for (int i = 0; i < r; i++) {scanf("%s", map[i]);for (int j = 0; j < c; j++) {if (map[i][j] == 'S') {start.x = i;start.y = j;} else if (map[i][j] == 'E') {end.x = i;end.y = j;}}}int shortestTime = shortestRescueTime(map, r, c, k, start, end);if (shortestTime == -1) {printf("oop!\n");} else {printf("%d\n", shortestTime);}}return 0;
}

在此解决方案中,我们使用了广度优先搜索(BFS)来寻找阿福救出公主的最短时间。我们使用一个队列来存储待处理的节点,并使用一个三维数组来记录已经访问过的位置和已经获得的宝石类型。通过遍历四个方向上的相邻位置,我们检查是否可以移动到该位置,如果可以移动,则将该位置加入队列,并更新已访问数组和距离数组。如果我们找到了公主的位置,我们返回当前的距离,表示成功救出公主。如果队列为空而且我们仍然没有找到公主的位置,则表示无法救出公主,返回-1。

请注意,此解决方案假设输入的地图是合法的,并且可以找到一条路径来救出公主。如果地图不合法或者无法救出公主,则输出"oop!"。

第3题:有多少种二叉树

输入n(1<n<13),求n个结点的二叉树有多少种形态
时间限制:1000
内存限制:65536
输入
整数n
输出
答案
样例输入
3
样例输出
5

这是一个经典的动态规划问题,称为卡塔兰数(Catalan Number)。可以使用动态规划的方法来解决。

首先,我们可以观察到,对于一个二叉树来说,根节点的左子树和右子树的结点数量之和等于总结点数量减去1。因此,我们可以用一个递归的方式来计算二叉树的种类数量。

定义一个函数 countTrees(n),表示 n 个结点的二叉树的种类数量。对于每一个 i,我们可以将其作为根节点,然后左子树的结点数量为 i-1,右子树的结点数量为 n-i。因此,可以得到递归关系式:

countTrees(n) = countTrees(0) * countTrees(n-1) + countTrees(1) * countTrees(n-2) + ... + countTrees(n-1) * countTrees(0)

初始条件为 countTrees(0) = 1,表示空树的一种形态。

下面是使用动态规划的 C 语言代码实现:

#include <stdio.h>long long countTrees(int n) {long long dp[n+1];dp[0] = 1;for (int i = 1; i <= n; i++) {dp[i] = 0;for (int j = 0; j < i; j++) {dp[i] += dp[j] * dp[i-j-1];}}return dp[n];
}int main() {int n;scanf("%d", &n);long long result = countTrees(n);printf("%lld\n", result);return 0;
}

在这个解决方案中,我们使用一个数组 dp 来存储计算过的结果,避免重复计算。我们使用两层循环,外层循环遍历结点数量,内层循环计算每个结点数量对应的二叉树种类数量。最后,输出 dp[n] 即为结果。

请注意,由于结果可能非常大,我们使用了 long long 类型来保存结果。

第4题:Sequence

给定m个数字序列,每个序列包含n个非负整数。我们从每一个序列中选取一个数字组成一个新的序列,显然一共可以构造出nm个新序列。接下来我们对每一个新的序列中的数字进行求和,一共会得到nm个和,请找出最小的n个和
时间限制:3000
内存限制:65536
输入
输入的第一行是一个整数T,表示测试用例的数量,接下来是T个测试用例的输入 每个测试用例输入的第一行是两个正整数m(0 < m <= 100)和n(0 < n <= 2000),然后有m行,每行有n个数,数字之间用空格分开,表示这m个序列 序列中的数字不会大于10000
输出
对每组测试用例,输出一行用空格隔开的数,表示最小的n个和
样例输入
1
2 3
1 2 3
2 2 3
样例输出
3 3 4

这是一个简单的问题,可以使用优先队列(堆)来解决。我们可以遍历每个序列,将序列中的数字依次加入优先队列,保持队列的大小为 n。这样,优先队列中的元素就是最小的 n 个数。

下面是使用 C 语言编写的解决方案:

#include <stdio.h>
#include <stdlib.h>#define MAX_SIZE 2000typedef struct {int value;int sequenceIndex;int numberIndex;
} Number;typedef struct {Number *data;int size;int capacity;
} MinHeap;MinHeap* createMinHeap(int capacity) {MinHeap *heap = (MinHeap*) malloc(sizeof(MinHeap));heap->data = (Number*) malloc(sizeof(Number) * capacity);heap->size = 0;heap->capacity = capacity;return heap;
}void destroyMinHeap(MinHeap *heap) {free(heap->data);free(heap);
}void swap(Number *a, Number *b) {Number temp = *a;*a = *b;*b = temp;
}void heapifyUp(MinHeap *heap, int index) {while (index > 0) {int parentIndex = (index - 1) / 2;if (heap->data[index].value < heap->data[parentIndex].value) {swap(&heap->data[index], &heap->data[parentIndex]);index = parentIndex;} else {break;}}
}void heapifyDown(MinHeap *heap, int index) {while (index < heap->size) {int leftChildIndex = 2 * index + 1;int rightChildIndex = 2 * index + 2;int smallestIndex = index;if (leftChildIndex < heap->size && heap->data[leftChildIndex].value < heap->data[smallestIndex].value) {smallestIndex = leftChildIndex;}if (rightChildIndex < heap->size && heap->data[rightChildIndex].value < heap->data[smallestIndex].value) {smallestIndex = rightChildIndex;}if (smallestIndex != index) {swap(&heap->data[index], &heap->data[smallestIndex]);index = smallestIndex;} else {break;}}
}void insertNumber(MinHeap *heap, int value, int sequenceIndex, int numberIndex) {if (heap->size == heap->capacity) {if (value >= heap->data[0].value) {return;}heap->data[0].value = value;heap->data[0].sequenceIndex = sequenceIndex;heap->data[0].numberIndex = numberIndex;heapifyDown(heap, 0);} else {heap->data[heap->size].value = value;heap->data[heap->size].sequenceIndex = sequenceIndex;heap->data[heap->size].numberIndex = numberIndex;heapifyUp(heap, heap->size);heap->size++;}
}void findSmallestSums(int m, int n, int sequences[][MAX_SIZE]) {MinHeap *heap = createMinHeap(n);for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {insertNumber(heap, sequences[i][j], i, j);}}for (int i = 0; i < n; i++) {printf("%d ", heap->data[i].value);}printf("\n");destroyMinHeap(heap);
}int main() {int t;scanf("%d", &t);while (t--) {int m, n;scanf("%d %d", &m, &n);int sequences[100][MAX_SIZE];for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {scanf("%d", &sequences[i][j]);}}findSmallestSums(m, n, sequences);}return 0;
}

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

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

相关文章

移动零00

题目链接 移动零 题目描述 注意点 将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序必须在不复制数组的情况下原地对数组进行操作 解答思路 采用双指针的思路&#xff0c;左指针指向已移动零的数组的尾部&#xff0c;右指针指向为移动零的数组的头部&…

Android-关于页面卡顿的排查工具与监测方案

作者&#xff1a;一碗清汤面 前言 关于卡顿这件事已经是老生常谈了&#xff0c;卡顿对于用户来说是敏感的&#xff0c;容易被用户直接感受到的。那么究其原因&#xff0c;卡顿该如何定义&#xff0c;对于卡顿的发生该如何排查问题&#xff0c;当线上用户卡顿时&#xff0c;在线…

宝塔面板一键部署Z-Blog博客 - 内网穿透实现公网访问

文章目录 1.前言2.网站搭建2.1. 网页下载和安装2.2.网页测试2.3.cpolar的安装和注册 3.本地网页发布3.1.Cpolar临时数据隧道3.2.Cpolar稳定隧道&#xff08;云端设置&#xff09;3.3.Cpolar稳定隧道&#xff08;本地设置&#xff09; 4.公网访问测试5.结语 1.前言 Ubuntu系统作…

ceph源码阅读 erasure-code

1、ceph纠删码 纠删码(Erasure Code)是比较流行的数据冗余的存储方法&#xff0c;将原始数据分成k个数据块(data chunk)&#xff0c;通过k个数据块计算出m个校验块(coding chunk)。把nkm个数据块保存在不同的节点&#xff0c;通过n中的任意k个块还原出原始数据。EC包含编码和解…

SpringMVC使用

文章目录 一.MVC基础概念1.MVC定义2.SpringMVC和MVC的关系 二.SpringMVC的使用1.RequestMapping2.获取参数1.获取单个参数2.传递对象3.后端参数重命名&#xff08;后端参数映射&#xff09;4.获取URL中参数PathVariable5.上传文件RequestPart6.获取Cookie/Session/header 3.返回…

Flink+Paimon多流拼接性能优化实战

目录 &#xff08;零&#xff09;本文简介 意外收获&#xff1a; &#xff08;一&#xff09;背景 &#xff08;二&#xff09;探索梳理过程 &#xff08;三&#xff09;源码改造 &#xff08;四&#xff09;修改效果 1、JOB状态 2、Level5的dataFile总大小 3、数据延…

企业网络安全:威胁情报解决方案

什么是威胁情报 威胁情报是网络安全的关键组成部分&#xff0c;可为潜在的恶意来源提供有价值的见解&#xff0c;这些知识可帮助组织主动识别和防止网络攻击&#xff0c;通过利用 STIX/TAXII 等威胁源&#xff0c;组织可以检测其网络中的潜在攻击&#xff0c;从而促进快速检测…

OJ练习第160题——LRU 缓存

LRU 缓存 力扣链接&#xff1a;146. LRU 缓存 题目描述 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类&#xff1a; LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存 int get(int key) 如果关键字 key 存在于缓…

用迅为RK3568开发板使用OpenCV处理图像颜色通道提取ROI

本小节代码在配套资料“iTOP-3568 开发板\03_【iTOP-RK3568 开发板】指南教程 \04_OpenCV 开发配套资料\07”目录下&#xff0c;如下图所示&#xff1a; 在计算机的色彩图像中存有三个通道&#xff0c;即 BGR 通道&#xff0c;根据三个颜色通道的亮度值来显示出不同的颜色&…

ubuntu22.04搭建verilator仿真环境

概述 操作系统为 Ubuntu(22.04.2 LTS)&#xff0c;本次安装verilator开源verilog仿真工具&#xff0c;进行RTL功能仿真。下面构建版本为5.008的verilator仿真环境。先看一下我系统的版本&#xff1a; 安装流程 安装依赖 sudo apt-get install git perl python3 make autoc…

Echarts遇到Vue3时遇到的问题

将vue2的Echarts代码迁移到了vue3项目上&#xff0c;引发的问题 问题描述&#xff1a; 1. 点击图例legend时刻度轴偏移&#xff0c;图像不展示&#xff0c;以及报错 初始chart正常.图 点击图例后的chart和报错.图 2. 调用resize()不生效且报错 初始正常.图 修改屏幕尺寸调用r…

ReentrantLock 原理

可以看到ReentrantLock提供了两个同步器&#xff0c;实现公平锁和非公平锁&#xff0c;都继承自AQS。 默认是非公平锁&#xff01; 下面是对ReentrantLock 的源码解析&#xff1a; 加锁源码 // Sync 继承自 AQS static final class NonfairSync extends Sync {private stati…