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

本文主要是介绍2023年09月 C/C++(八级)真题解析#中国电子学会#全国青少年软件编程等级考试,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在这里插入图片描述

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

第1题:最短路径问题

平面上有n个点(n<=100),每个点的坐标均在-10000~10000之间。其中的一些点之间有连线。
若有连线,则表示可从一个点到达另一个点,即两点间有通路,通路的距离为两点间的直线距离。现在的任务是找出从一点到另一点之间的最短路径。
时间限制:1000
内存限制:131072
输入
共n+m+3行,其中: 第一行为整数n。 第2行到第n+1行(共n行) ,每行两个整数x和y,描述了一个点的坐标。 第n+2行为一个整数m,表示图中连线的个数。 此后的m 行,每行描述一条连线,由两个整数i和j组成,表示第i个点和第j个点之间有连线。 最后一行:两个整数s和t,分别表示源点和目标点。
输出
仅一行,一个实数(保留两位小数),表示从s到t的最短路径长度。
样例输入
5
0 0
2 0
2 2
0 2
3 1
5
1 2
1 3
1 4
2 5
3 5
1 5
样例输出
3.41

下面是一个使用C语言解决最短路径问题的示例代码:

#include <stdio.h>
#include <math.h>#define MAX_POINTS 100typedef struct {int x;int y;
} Point;double distance(Point p1, Point p2) {int dx = p2.x - p1.x;int dy = p2.y - p1.y;return sqrt(dx * dx + dy * dy);
}double shortestPath(Point points[], int n, int connections[][2], int m, int source, int target) {double dist[MAX_POINTS];int visited[MAX_POINTS] = {0};int i, j;for (i = 0; i < n; i++) {dist[i] = INFINITY;}dist[source] = 0;for (i = 0; i < n - 1; i++) {int minIndex = -1;double minDist = INFINITY;for (j = 0; j < n; j++) {if (!visited[j] && dist[j] < minDist) {minIndex = j;minDist = dist[j];}}visited[minIndex] = 1;for (j = 0; j < m; j++) {int u = connections[j][0];int v = connections[j][1];double d = distance(points[u], points[v]);if (!visited[v] && dist[u] + d < dist[v]) {dist[v] = dist[u] + d;}}}return dist[target];
}int main() {int n, m;Point points[MAX_POINTS];int connections[MAX_POINTS][2];int source, target;int i;scanf("%d", &n);for (i = 0; i < n; i++) {scanf("%d %d", &points[i].x, &points[i].y);}scanf("%d", &m);for (i = 0; i < m; i++) {scanf("%d %d", &connections[i][0], &connections[i][1]);}scanf("%d %d", &source, &target);double shortestDist = shortestPath(points, n, connections, m, source - 1, target - 1);printf("%.2f\n", shortestDist);return 0;
}

解释:

首先,我们定义了一个Point结构体来表示点的坐标。

distance()函数用于计算两个点之间的直线距离。

shortestPath()函数实现了Dijkstra算法来找到最短路径的长度。它使用一个距离数组dist来保存每个点到源点的最短距离,visited数组用于标记已经访问过的点。在每一轮迭代中,它选择距离源点最近且未访问过的点作为当前点,然后更新与当前点相邻的点的最短距离。

main()函数中,我们首先读取输入数据,包括点的坐标、连线的信息以及源点和目标点的编号。

然后调用shortestPath()函数来计算最短路径的长度,并打印结果。

第2题:控制公司

有些公司是其他公司的部分拥有者,因为他们获得了其他公司发行的股票的一部分。例如,福特公司拥有马自达公司12%的股票。据说,如果至少满足了以下条件之一,公司A就可以控制公司B了:
l 公司A = 公司B。
l 公司A拥有大于50%的公司B的股票。
l 公司A控制K(K >= 1)个公司,记为C1, …, CK,每个公司Ci拥有xi%的公司B的股票,并且x1+ … + xK > 50%。(ps:A可以控制自己,即Ci可以为A)
你将被给予一系列的三对数(i,j,p),表明公司i拥有公司j的p%的股票。计算所有的数对(h,s),表明公司h控制公司s。
写一个程序读入三对数(i,j,p),并且找出所有的数对(h,s),使得公司h控制公司s。
时间限制:1000
内存限制:65536
输入
第一行: N,表明接下来三对数的数量。 第二行到第N+1行:每行三个整数作为一个三对数(i,j,p),如上文所述。 I,J≤100,N,P≤100
输出
输出零个或更多个的控制其他公司的公司。每行包括两个整数表明序号为第一个整数的公司控制了序号为第二个整数的公司。将输出的每行以第一个数字升序排列(并且第二个数字也升序排列来避免并列)。请不要输出控制自己的公司。
样例输入
3
1 2 80
2 3 80
3 1 20
样例输出
1 2
1 3
2 3

下面是一个使用C语言解决控制公司问题的示例代码:

#include <stdio.h>#define MAX_COMPANIES 100int ownership[MAX_COMPANIES][MAX_COMPANIES] = {0};
int controlled[MAX_COMPANIES][MAX_COMPANIES] = {0};
int n;void dfs(int company, int owner) {int i;for (i = 0; i < n; i++) {if (ownership[company][i] > 0 && controlled[owner][i] == 0) {controlled[owner][i] = 1;dfs(i, owner);}}
}int main() {scanf("%d", &n);int i, j, p;while (n--) {scanf("%d %d %d", &i, &j, &p);ownership[i - 1][j - 1] = p;}for (i = 0; i < MAX_COMPANIES; i++) {controlled[i][i] = 1;for (j = 0; j < MAX_COMPANIES; j++) {if (ownership[i][j] > 50) {controlled[i][j] = 1;dfs(j, i);}}}for (i = 0; i < MAX_COMPANIES; i++) {for (j = 0; j < MAX_COMPANIES; j++) {if (controlled[i][j] && i != j) {printf("%d %d\n", i + 1, j + 1);}}}return 0;
}

解释:

首先,我们定义了两个二维数组ownershipcontrolled,用于存储公司之间的股权关系和控制关系。

dfs()函数是一个深度优先搜索算法,用于遍历公司之间的股权关系,并更新控制关系。

main()函数中,我们首先从输入中读取公司之间的股权关系,并将其保存在ownership数组中。

然后,使用两个嵌套循环遍历所有公司,如果某个公司拥有超过50%的另一个公司的股权,则将其标记为控制关系,并调用dfs()函数来更新其他受控公司。

最后,我们遍历controlled数组,输出所有的控制关系。

第3题:发现它,抓住它

一个城市中有两个犯罪团伙A和B,你需要帮助警察判断任意两起案件是否是同一个犯罪团伙所为,警察所获得的信息是有限的。假设现在有N起案件(N<=100000),编号为1到N,每起案件由团伙A或团伙B所为。你将按时间顺序获得M条信息(M<=100000),这些信息分为两类:
1、D [a] [b]
其中[a]和[b]表示两起案件的编号,这条信息表明它们属于不同的团伙所为
2、A [a] [b]
其中[a]和[b]表示两起案件的编号,这条信息需要你回答[a]和[b]是否是同一个团伙所为
注意你获得信息的时间是有先后顺序的,在回答的时候只能根据已经接收到的信息做出判断。
时间限制:1000
内存限制:65536
输入
第一行是测试数据的数量T(1<=T<=20)。 每组测试数据的第一行包括两个数N和M,分别表示案件的数量和信息的数量,其后M行表示按时间顺序收到的M条信息。
输出
对于每条需要回答的信息,你需要输出一行答案。如果是同一个团伙所为,回答"In the same gang.“,如果不是,回答"In different gangs.”,如果不确定,回答”Not sure yet."。
样例输入
1
5 5
A 1 2
D 1 2
A 1 2
D 2 4
A 1 4
样例输出
Not sure yet.
In different gangs.
In the same gang.

下面是一个使用C语言解决判断案件团伙问题的示例代码:

#include <stdio.h>#define MAX_CASES 100000int gang[MAX_CASES];int find(int x) {if (gang[x] == x)return x;return gang[x] = find(gang[x]);
}void merge(int x, int y) {int fx = find(x);int fy = find(y);if (fx != fy)gang[fy] = fx;
}int main() {int T;scanf("%d", &T);while (T--) {int N, M;scanf("%d %d", &N, &M);// 初始化每个案件所属的团伙for (int i = 1; i <= N; i++)gang[i] = i;char op;int a, b;while (M--) {scanf(" %c %d %d", &op, &a, &b);if (op == 'A') {// 判断是否属于同一个团伙if (find(a) == find(b))printf("In the same gang.\n");elseprintf("In different gangs.\n");} else if (op == 'D') {// 合并两个团伙merge(a, b);}}}return 0;
}

解释:

首先,我们定义了一个整数数组gang,用于存储每个案件所属的团伙。

find()函数是一个递归的查找函数,用于找到某个案件所属的团伙的根节点。

merge()函数用于合并两个团伙,将其中一个团伙的根节点指向另一个团伙的根节点。

main()函数中,我们首先读取测试数据的数量T,然后开始处理每组测试数据。

对于每组测试数据,我们首先根据案件数量N初始化每个案件所属的团伙为自身。

然后,依次读取每条信息,并根据信息的类型进行相应的操作。如果是类型为A的信息,我们调用find()函数判断两个案件是否属于同一个团伙;如果是类型为D的信息,我们调用merge()函数合并两个团伙。

最后,根据判断的结果输出相应的答案。

第4题:最短路

给定一个n个点, m条边的有向图, 求从点S出发, 到其它所有点的最短路径.
时间限制:2000
内存限制:65536
输入
第一行一个整数T, 表示有T组数据 对于每组测试数据, 第一行三个整数n, m, S, 表示有n个点, m条边, 起点为S. 接下来m行, 每行三个整数x, y, z, 代表从x到y有长度为z的边 点的编号从1到n T <= 10, n <= 10000, m <= 20000, |z| <= 10000. 所有数据的n之和 <= 30000, 所有数据的m之和 <= 60000.
输出
对于每组数据: 如果从S点出发可以走入负圈 (即到某些点的最短路径可以无限小), 那么输出一行Error. 否则, 输出一行用空格分隔的n个整数, 其中第i个整数表示从S点到i点的最短路长度. 如果从S点无法到达i点, 则第i个输出为”null”.
样例输入
4
5 7 1
1 2 3
2 3 4
3 4 8
1 3 9
4 5 1
1 4 5
1 5 10
4 4 1
1 2 -4
2 3 8
1 3 5
3 4 0
3 3 2
1 2 -3
2 3 -4
3 1 6
4 2 1
1 2 1
3 4 2
样例输出
0 3 7 5 6
0 -4 4 4
Error
0 1 null null

下面是一个使用C语言解决最短路径问题的示例代码,使用Dijkstra算法:

#include <stdio.h>
#include <stdbool.h>
#include <limits.h>#define MAX_NODES 10001
#define MAX_EDGES 60001
#define INF INT_MAXtypedef struct {int node;int cost;
} Edge;typedef struct {Edge edges[MAX_EDGES];int count;
} AdjList;AdjList graph[MAX_NODES];
int dist[MAX_NODES];void dijkstra(int start, int n) {bool visited[MAX_NODES];int i, j;for (i = 1; i <= n; i++) {dist[i] = INF;visited[i] = false;}dist[start] = 0;for (i = 1; i <= n; i++) {int u = -1;for (j = 1; j <= n; j++) {if (!visited[j] && (u == -1 || dist[j] < dist[u])) {u = j;}}if (dist[u] == INF) {break;}visited[u] = true;for (j = 0; j < graph[u].count; j++) {int v = graph[u].edges[j].node;int cost = graph[u].edges[j].cost;if (dist[u] + cost < dist[v]) {dist[v] = dist[u] + cost;}}}
}int main() {int T;scanf("%d", &T);while (T--) {int n, m, S;scanf("%d %d %d", &n, &m, &S);int i;for (i = 1; i <= n; i++) {graph[i].count = 0;}for (i = 0; i < m; i++) {int x, y, z;scanf("%d %d %d", &x, &y, &z);graph[x].edges[graph[x].count].node = y;graph[x].edges[graph[x].count].cost = z;graph[x].count++;}dijkstra(S, n);for (i = 1; i <= n; i++) {if (dist[i] == INF) {printf("null ");} else {printf("%d ", dist[i]);}}printf("\n");}return 0;
}

解释:

首先,我们定义了一个结构体Edge,用于表示图中的边,包括目标节点和边的权重。

然后,我们定义了一个结构体AdjList,用于表示邻接表,其中包含一个Edge类型的数组以及边的数量。

我们使用邻接表数组graph来表示图,每个节点对应一个邻接表。

dijkstra()函数是一个实现Dijkstra算法的函数,用于计算从起点出发到其他所有点的最短路径。

main()函数中,我们首先读取测试数据的数量T,然后开始处理每组测试数据。

对于每组测试数据,我们首先根据节点数量n初始化图的邻接表。

然后,依次读取每条边的信息,并将其添加到对应节点的邻接表中。

接下来,我们调用dijkstra()函数计算从起点S出发到其他所有点的最短路径。

最后,我们根据最短路径的计算结果输出每个节点的最短路径长度或"null"。

这篇关于2023年09月 C/C++(八级)真题解析#中国电子学会#全国青少年软件编程等级考试的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/264242

相关文章

Python获取中国节假日数据记录入JSON文件

《Python获取中国节假日数据记录入JSON文件》项目系统内置的日历应用为了提升用户体验,特别设置了在调休日期显示“休”的UI图标功能,那么问题是这些调休数据从哪里来呢?我尝试一种更为智能的方法:P... 目录节假日数据获取存入jsON文件节假日数据读取封装完整代码项目系统内置的日历应用为了提升用户体验,

使用Jackson进行JSON生成与解析的新手指南

《使用Jackson进行JSON生成与解析的新手指南》这篇文章主要为大家详细介绍了如何使用Jackson进行JSON生成与解析处理,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 核心依赖2. 基础用法2.1 对象转 jsON(序列化)2.2 JSON 转对象(反序列化)3.

揭秘Python Socket网络编程的7种硬核用法

《揭秘PythonSocket网络编程的7种硬核用法》Socket不仅能做聊天室,还能干一大堆硬核操作,这篇文章就带大家看看Python网络编程的7种超实用玩法,感兴趣的小伙伴可以跟随小编一起... 目录1.端口扫描器:探测开放端口2.简易 HTTP 服务器:10 秒搭个网页3.局域网游戏:多人联机对战4.

Springboot @Autowired和@Resource的区别解析

《Springboot@Autowired和@Resource的区别解析》@Resource是JDK提供的注解,只是Spring在实现上提供了这个注解的功能支持,本文给大家介绍Springboot@... 目录【一】定义【1】@Autowired【2】@Resource【二】区别【1】包含的属性不同【2】@

SpringCloud动态配置注解@RefreshScope与@Component的深度解析

《SpringCloud动态配置注解@RefreshScope与@Component的深度解析》在现代微服务架构中,动态配置管理是一个关键需求,本文将为大家介绍SpringCloud中相关的注解@Re... 目录引言1. @RefreshScope 的作用与原理1.1 什么是 @RefreshScope1.

Java并发编程必备之Synchronized关键字深入解析

《Java并发编程必备之Synchronized关键字深入解析》本文我们深入探索了Java中的Synchronized关键字,包括其互斥性和可重入性的特性,文章详细介绍了Synchronized的三种... 目录一、前言二、Synchronized关键字2.1 Synchronized的特性1. 互斥2.

Java的IO模型、Netty原理解析

《Java的IO模型、Netty原理解析》Java的I/O是以流的方式进行数据输入输出的,Java的类库涉及很多领域的IO内容:标准的输入输出,文件的操作、网络上的数据传输流、字符串流、对象流等,这篇... 目录1.什么是IO2.同步与异步、阻塞与非阻塞3.三种IO模型BIO(blocking I/O)NI

Python 中的异步与同步深度解析(实践记录)

《Python中的异步与同步深度解析(实践记录)》在Python编程世界里,异步和同步的概念是理解程序执行流程和性能优化的关键,这篇文章将带你深入了解它们的差异,以及阻塞和非阻塞的特性,同时通过实际... 目录python中的异步与同步:深度解析与实践异步与同步的定义异步同步阻塞与非阻塞的概念阻塞非阻塞同步

C++ 中的 if-constexpr语法和作用

《C++中的if-constexpr语法和作用》if-constexpr语法是C++17引入的新语法特性,也被称为常量if表达式或静态if(staticif),:本文主要介绍C++中的if-c... 目录1 if-constexpr 语法1.1 基本语法1.2 扩展说明1.2.1 条件表达式1.2.2 fa

Python异步编程中asyncio.gather的并发控制详解

《Python异步编程中asyncio.gather的并发控制详解》在Python异步编程生态中,asyncio.gather是并发任务调度的核心工具,本文将通过实际场景和代码示例,展示如何结合信号量... 目录一、asyncio.gather的原始行为解析二、信号量控制法:给并发装上"节流阀"三、进阶控制