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

news2024/11/24 19:13:45

在这里插入图片描述

第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 20000

int 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 8

int 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 4000

bool 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 200

int 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.coloradmin.cn/o/949826.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

亚马逊云科技 云技能孵化营——我的云技能之旅

文章目录 每日一句正能量前言活动流程后记 每日一句正能量 不能在已经获得足够多的成功时&#xff0c;还对自己的能力保持怀疑&#xff0c;露出自信的微笑&#xff0c;走出自信的步伐&#xff0c;做一个自信的人&#xff01; 前言 亚马逊云科技 (Amazon Web Services) 是全球云…

Kao框架学习

中间件&#xff1a;洋葱模型 这是官网上给出的示例&#xff0c;从logger依次往下执行&#xff0c;执行到最底层的response往回退&#xff0c;结构很像同心圆的洋葱从外层向内层再由内层向外层。 next表示暂停当前层的代码进入下一层&#xff0c; 当最后一层执行完毕开始回溯&a…

学习完毕JavaSE的感想

今天&#xff0c;把Java复习完毕了&#xff0c;之前学习的时候&#xff0c;学校里学的总是有限的 &#xff0c;自己上手操作之后才发觉差的很多&#xff0c;部署服务器发现要学操作系统&#xff0c;学完了web基础 &#xff0c;又发现还得学前后端分离vue react这些&#xff0c;…

基于ensp的中大型企业网络安全解决方案的设计与实施

一、需求背景 公司部门具体背景&#xff1a;公司共设有人事部、财务部、销售部、市场部四个部门以及一个员工宿舍楼&#xff0c;公司有对外互联网业务需要提供。公司内存在重要部门需要保护数据安全以及访问控制。 &#xff08;1&#xff09;根据客户需求、部门、拓扑&#xf…

代码搜索技巧

在IDE中搜索代码时&#xff0c;经常会被相近的无关代码干扰&#xff0c;如筛选所有使用协程的代码段&#xff0c; 可见有大量“噪音”。 可使用IDE提供的正则表达式功能 如 使用 \bgo ,即匹配go开头的&#xff0c;且之后为空格的所有选项 使用 \bgo func,即匹配到了所有使用协程…

C++学习vector

1,把list的相关函数都实现出来&#xff08;未完&#xff09; 2&#xff0c; 运行结果&#xff1a;

等保测评各个级别的详细内容

等保测评是指信息系统安全等级保护测评&#xff0c;是我国信息安全领域中的一项重要工作。根据国家标准《信息系统安全等级保护基本要求》(GB/T 22239-2008)和《信息系统安全等级保护测评技术要求》(GB/T 25070-2010)。 等保测评分为五个级别&#xff0c;分别是&#xff1a;一级…

达梦数据库管理用户和创建用户介绍

概述 本文主要对达梦数据库管理用户和创建用户进行介绍和总结。 1.管理用户介绍 1.1 达梦安全机制 任何数据库设计和使用都需要考虑安全机制&#xff0c;达梦数据库采用“三权分立”或“四权分立”的安全机制&#xff0c;将系统中所有的权限按照类型进行划分&#xff0c;为每…

JZ12 矩阵中的路径

剑指Offer编程链接&#xff1a;JZ12 题目描述&#xff1a; 思路&#xff1a;递归回溯的方法&#xff0c;总结一下什么情况需要使用递归&#xff1a; 递归在解决问题时&#xff0c;通常涉及以下情况&#xff1a; 问题可被分解为较小的相似子问题。子问题与原问题具有相同的结…

eclipse设置字体大小

打开IDE&#xff0c;选择window->perferences 选择颜色与字体&#xff0c;选择basic 选中text-font之后选择编辑 选择合适的大小之后选择应用并关闭即可 结果

权限提升-Windows本地提权-AT+SC+PS命令-进程迁移-令牌窃取-getsystem+UAC

权限提升基础信息 1、具体有哪些权限需要我们了解掌握的&#xff1f; 后台权限&#xff0c;网站权限&#xff0c;数据库权限&#xff0c;接口权限&#xff0c;系统权限&#xff0c;域控权限等 2、以上常见权限获取方法简要归类说明&#xff1f; 后台权限&#xff1a;SQL注入,数…

ELK日志收集系统

一、概述 1、ELK由三个组件构成 2、作用 日志收集 日志分析 日志可视化 3、为什么使用&#xff1f; 日志对于分析系统、应用的状态十分重要&#xff0c;但一般日志的量会比较大&#xff0c;并且比较分散。 如果管理的服务器或者程序比较少的情况我们还可以逐一…

数据结构学习 --4 串

数据结构学习 --1 绪论 数据结构学习 --2 线性表 数据结构学习 --3 栈&#xff0c;队列和数组 数据结构学习 --4 串 数据结构学习 --5 树和二叉树 数据结构学习 --6 图 数据结构学习 --7 查找 数据结构学习 --8 排序 本人学习记录使用 希望对大家帮助 不当之处希望大家帮忙纠正…

二极管:常用二极管封装

常用二极管封装 1、DO-41 2、DO-201AD 3、DO-35 4、LL-34 5、DO-214AC (SMA) 6、SMB

电脑数据丢失如何恢复?最常见的2种数据恢复方法!

大家使用电脑的时候是否有发生过不小心删除数据&#xff0c;或者数据不明丢失的情况呢&#xff1f;相信九成都是有的&#xff0c;那么当你的数据不小心删除或是丢失的话&#xff0c;有没有电脑数据恢复方法&#xff1f;其实很多人当自己电脑的数据丢失后&#xff0c;如果不是很…

一直傻傻分不清 count(*) count(id) count(1) 这次终于整明白了

COUNT(*)、COUNT(id) 和 COUNT(1) 是用于计算行数的 SQL 聚合函数&#xff0c;它们在某些方面有一些区别。 - COUNT(*)&#xff1a;COUNT(*) 是一种特殊的语法&#xff0c;它返回结果集中的行数&#xff0c;不考虑任何列的值。它会将表中的每一行都计数&#xff0c;包括含有NU…

ToBeWritten之威胁情报

也许每个人出生的时候都以为这世界都是为他一个人而存在的&#xff0c;当他发现自己错的时候&#xff0c;他便开始长大 少走了弯路&#xff0c;也就错过了风景&#xff0c;无论如何&#xff0c;感谢经历 转移发布平台通知&#xff1a;将不再在CSDN博客发布新文章&#xff0c;敬…

【LeetCode】剑指 Offer <二刷>(1)

目录 前言&#xff1a; 题目&#xff1a;剑指 Offer 03. 数组中重复的数字 - 力扣&#xff08;LeetCode&#xff09; 题目的接口&#xff1a; 解题思路&#xff1a; 代码&#xff1a; 过啦&#xff01;&#xff01;&#xff01; 写在最后&#xff1a; 前言&#xff1a; …

Charles调试请求

问题 需要调试特定的一个请求。 解决 选中调试 选中一个请求&#xff0c;右键菜单选中调试即可。 启用调试模式 勾选顶部控制按钮&#xff0c;启用调试模式&#xff0c;右下角会出现调试启用状态。 调试请求管理 通过顶部proxy➡️Breakpoint Settings…菜单&#xf…

企业诊断屋:在线小说企业如何用A/B测试赋能业务

更多技术交流、求职机会&#xff0c;欢迎关注字节跳动数据平台微信公众号&#xff0c;回复【1】进入官方交流群 近两年来&#xff0c;在线小说领域业务发展“降速”&#xff0c;相较于几年前的快速扩张&#xff0c;2022年后国内在线小说企业步入瓶颈期。但与此同&#xff0c;新…