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

news2025/1/14 0:50:19

在这里插入图片描述

第1题:数字变换

给定一个包含5个数字(0-9)的字符串,例如 “02943”,请将“12345”变换到它。 你可以采取3种操作进行变换
(1)交换相邻的两个数字
(2)将一个数字加1。如果加1后大于9,则变为0
(3)将一个数字加倍。如果加倍后大于9,则将其变为加倍后的结果除以10的余数。
最多只能用第2种操作3次,第3种操作2次 求最少经过多少次操作可以完成变换。
时间限制:1000
内存限制:65536
输入
有最多 100,000 组数据 每组数据就是包含5个数字的字符串
输出
对每组数据,输出将12345变换到给定字符串所需要的最少操作步数。如果无法变换成功,输出-1
样例输入
12435
99999
12374
样例输出
1
-1
3
提示
由于测试数据太多,如果对每组数据都从头进行搜索,就会超时。 建议先做预处理,即以“12345”作为初始状态做一遍彻底的广搜,找出“12345”经合法变换能够到达的所有字符串,并记录到达这些字符串各需要多少步操作。 然后对读入的每组数据,在上述预处理记录的结果中进行查询即可。

这个问题可以使用广度优先搜索(BFS)来解决。首先,我们以"12345"作为初始状态,通过合法的操作进行广度优先搜索,找出所有可以到达的字符串,并记录到达这些字符串所需的最少操作步数。然后,对于每组输入数据,我们可以直接在记录的结果中进行查询,找到所需的最少操作步数。

下面是一个使用C语言实现的示例代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_STATES 100000

// 定义状态结构体
typedef struct {
    char state[6];  // 保存状态的字符串
    int steps;      // 到达该状态所需的步数
} State;

// 定义队列结构体
typedef struct {
    State data[MAX_STATES];
    int front;
    int rear;
} Queue;

// 初始化队列
void initQueue(Queue *queue) {
    queue->front = queue->rear = 0;
}

// 判断队列是否为空
int isQueueEmpty(Queue *queue) {
    return queue->front == queue->rear;
}

// 入队
void enqueue(Queue *queue, State state) {
    queue->data[queue->rear] = state;
    queue->rear = (queue->rear + 1) % MAX_STATES;
}

// 出队
State dequeue(Queue *queue) {
    State state = queue->data[queue->front];
    queue->front = (queue->front + 1) % MAX_STATES;
    return state;
}

// 判断字符串是否已经存在于队列中
int isStateVisited(Queue *queue, char *state) {
    int i;
    for (i = queue->front; i != queue->rear; i = (i + 1) % MAX_STATES) {
        if (strcmp(queue->data[i].state, state) == 0) {
            return 1;
        }
    }
    return 0;
}

// 进行广度优先搜索
void bfs() {
    Queue queue;
    initQueue(&queue);
    
    State startState;
    strcpy(startState.state, "12345");
    startState.steps = 0;
    enqueue(&queue, startState);
    
    int i, j;
    while (!isQueueEmpty(&queue)) {
        State currentState = dequeue(&queue);
        int steps = currentState.steps;
        
        if (steps > 3) {
            // 超过最大步数限制,不再继续搜索
            break;
        }
        
        // 尝试进行操作1:交换相邻的两个数字
        for (i = 0; i < 4; i++) {
            for (j = i + 1; j < 5; j++) {
                State nextState = currentState;
                char temp = nextState.state[i];
                nextState.state[i] = nextState.state[j];
                nextState.state[j] = temp;
                nextState.steps = steps + 1;
                if (!isStateVisited(&queue, nextState.state)) {
                    enqueue(&queue, nextState);
                }
            }
        }
        
        // 尝试进行操作2:将一个数字加1
        for (i = 0; i < 5; i++) {
            State nextState = currentState;
            nextState.state[i] = (nextState.state[i] - '0' + 1) % 10 + '0';
            nextState.steps = steps + 1;
            if (!isStateVisited(&queue, nextState.state)) {
                enqueue(&queue, nextState);
            }
        }
        
        // 尝试进行操作3:将一个数字加倍
        for (i = 0; i < 5; i++) {
            State nextState = currentState;
            int num = nextState.state[i] - '0';
            nextState.state[i] = ((num * 2) % 10) + '0';
            nextState.steps = steps + 1;
            if (!isStateVisited(&queue, nextState.state)) {
                enqueue(&queue, nextState);
            }
        }
    }
}

int main() {
    bfs();  // 预处理,进行广度优先搜索
    
    int T;
    scanf("%d", &T);
    
    while (T--) {
        char target[6];
        scanf("%s", target);
        
        Queue queue;
        initQueue(&queue);
        
        State startState;
        strcpy(startState.state, target);
        startState.steps = 0;
        enqueue(&queue, startState);
        
        int minSteps = -1;
        
        while (!isQueueEmpty(&queue)) {
           State currentState = dequeue(&queue);
            int steps = currentState.steps;
            
            if (strcmp(currentState.state, "12345") == 0) {
                // 找到目标状态
                minSteps = steps;
                break;
            }
            
            if (steps > 3) {
                // 超过最大步数限制,不再继续搜索
                break;
            }
            
            // 尝试进行操作1:交换相邻的两个数字
            for (i = 0; i < 4; i++) {
                for (j = i + 1; j < 5; j++) {
                    State nextState = currentState;
                    char temp = nextState.state[i];
                    nextState.state[i] = nextState.state[j];
                    nextState.state[j] = temp;
                    nextState.steps = steps + 1;
                    if (!isStateVisited(&queue, nextState.state)) {
                        enqueue(&queue, nextState);
                    }
                }
            }
            
            // 尝试进行操作2:将一个数字加1
            for (i = 0; i < 5; i++) {
                State nextState = currentState;
                nextState.state[i] = (nextState.state[i] - '0' + 1) % 10 + '0';
                nextState.steps = steps + 1;
                if (!isStateVisited(&queue, nextState.state)) {
                    enqueue(&queue, nextState);
                }
            }
            
            // 尝试进行操作3:将一个数字加倍
            for (i = 0; i < 5; i++) {
                State nextState = currentState;
                int num = nextState.state[i] - '0';
                nextState.state[i] = ((num * 2) % 10) + '0';
                nextState.steps = steps + 1;
                if (!isStateVisited(&queue, nextState.state)) {
                    enqueue(&queue, nextState);
                }
            }
        }
        
        printf("%d\n", minSteps);
    }
    
    return 0;
}

这个代码首先进行预处理,使用广度优先搜索找出所有可以从"12345"变换到的字符串,并记录到达这些字符串所需的最少操作步数。然后,对于每组输入数据,使用另一个队列进行广度优先搜索,找到从目标字符串到"12345"所需的最少操作步数,并输出结果。

请注意,这个代码使用了队列来实现广度优先搜索,并使用了一个布尔数组来记录已经访问过的状态,以避免重复搜索。同时,为了优化性能,在进行广度优先搜索时,限制了最大步数为3,超过这个步数的状态将不再考虑。

第2题:圣诞老人的礼物

圣诞节来临了,在城市A中圣诞老人准备分发糖果,现在有多箱不同的糖果,每箱糖果有自己的价值和重量,每箱糖果都可以拆分成任意散装组合带走。圣诞老人的驯鹿最多只能承受一定重量的糖果,请问圣诞老人最多能带走多大价值的糖果。
时间限制:1000
内存限制:65536
输入
第一行由两个部分组成,分别为糖果箱数正整数n(1 = n = 100),驯鹿能承受的最大重量正整数w(0 w 10000),两个数用空格隔开。其余n行每行对应一箱糖果,由两部分组成,分别为一箱糖果的价值正整数v和重量正整数w,中间用空格隔开。
输出
输出圣诞老人能带走的糖果的最大总价值,保留1位小数。输出为一行,以换行符结束。
样例输入
4 15
100 4
412 8
266 7
591 2
样例输出
1193.0

最容易实现的方法是使用贪心算法。下面是使用贪心算法的简单实现:

#include <stdio.h>

#define MAX_N 100

// 定义糖果的结构体
typedef struct {
    int value;
    int weight;
} Candy;

// 贪心算法函数
double greedyAlgorithm(Candy candies[], int n, int maxWeight) {
    // 根据单位重量的价值进行排序
    for (int i = 0; i < n - 1; i++) {
        for (int j = 0; j < n - i - 1; j++) {
            double valuePerWeight1 = (double)candies[j].value / candies[j].weight;
            double valuePerWeight2 = (double)candies[j + 1].value / candies[j + 1].weight;
            
            if (valuePerWeight1 < valuePerWeight2) {
                // 交换糖果的位置
                Candy temp = candies[j];
                candies[j] = candies[j + 1];
                candies[j + 1] = temp;
            }
        }
    }
    
    double maxTotal = 0;
    int currentWeight = 0;
    
    for (int i = 0; i < n; i++) {
        if (currentWeight + candies[i].weight <= maxWeight) {
            // 将当前糖果全部带走
            maxTotal += candies[i].value;
            currentWeight += candies[i].weight;
        } else {
            // 部分带走当前糖果
            double remainingWeight = maxWeight - currentWeight;
            double remainingValue = (double)candies[i].value * remainingWeight / candies[i].weight;
            maxTotal += remainingValue;
            break;
        }
    }
    
    return maxTotal;
}

int main() {
    int n, maxWeight;
    Candy candies[MAX_N];
    
    // 读取输入
    scanf("%d %d", &n, &maxWeight);
    for (int i = 0; i < n; i++) {
        scanf("%d %d", &candies[i].value, &candies[i].weight);
    }
    
    // 使用贪心算法
    double maxTotal = greedyAlgorithm(candies, n, maxWeight);
    
    // 输出结果
    printf("%.1lf\n", maxTotal);
    
    return 0;
}

这个方法的思路是先将糖果按照单位重量的价值进行排序,然后从价值最高的糖果开始,依次尽可能地带走糖果,直到达到驯鹿能够承受的最大重量。如果某个糖果无法完全带走,则部分带走该糖果。最后,将带走的糖果的总价值进行累加,即为圣诞老人能够带走的糖果的最大总价值。

第3题:忍者道具

忍者道具有很多种,苦无,飞镖,震爆弹。L君热衷于收集忍者道具,现在他有N个道具,每个道具的重量分别是C1、C2…CN。现在他想把这N个道具装到载重量为W的工具包里,请问他最少需要多少个工具包?
时间限制:1000
内存限制:65536
输入
第一行包含两个用空格隔开的整数,N和W。 接下来N行每行一个整数,其中第i+1行的整数表示第i个道具的重量Ci。
输出
输出一个整数,最少需要多少个工具包。
样例输入
5 1996
1
2
1994
12
29
样例输出
2
提示
对于100%的数据,1=N=18,1=Ci=W=10^8。

该题可以使用贪心算法来解决,下面是C语言代码:

#include <stdio.h>

#define MAX_N 18

int main() {
    int N, W;
    int weights[MAX_N];
    
    // 读取输入
    scanf("%d %d", &N, &W);
    for (int i = 0; i < N; i++) {
        scanf("%d", &weights[i]);
    }
    
    // 贪心算法求解
    int numBags = 0;
    int currentWeight = 0;
    
    for (int i = 0; i < N; i++) {
        if (currentWeight + weights[i] <= W) {
            // 当前工具包可以容纳该道具
            currentWeight += weights[i];
        } else {
            // 当前工具包无法容纳该道具,需要使用新的工具包
            numBags++;
            currentWeight = weights[i];
        }
    }
    
    // 若还有剩余道具未放入工具包,则需要额外的工具包
    if (currentWeight > 0) {
        numBags++;
    }
    
    // 输出结果
    printf("%d\n", numBags);
    
    return 0;
}

该算法的思路是按照道具的重量顺序进行遍历,如果当前工具包的载重量可以容纳当前道具,则将道具放入工具包中;否则,需要使用新的工具包来装载该道具。最后,如果还有剩余的道具未放入工具包,则需要额外的工具包。输出最少需要的工具包数量即为解。

第4题:求逆序对问题

给定N个数的序列a1,a2,…aN,定义一个数对(ai, aj)为“重要逆序对”的充要条件为 i j 且 ai 2aj。求给定序列中“重要逆序对”的个数。
时间限制:1000
内存限制:256000
输入
本题有多个测试点,每个测试点分为两行:第一行为序列中数字的个数N(1 ≤ N ≤ 200000),第二行为序列a1, a2 … aN(0 ≤a ≤ 10000000),由空格分开。N=0表示输入结束。
输出
每个测试点一行,输出一个整数,为给序列中“重要逆序对”的个数。
样例输入
10
0 9 8 7 6 5 4 3 2 1
0
样例输出
16
提示
请注意答案范围,如果使用printf输出long long类型,请用%lld

以下是使用分治技术来解决求逆序对问题的C语言代码:

#include <stdio.h>

#define MAX_N 200000

long long merge(int arr[], int temp[], int left, int mid, int right) {
    int i = left;     // 左子数组的起始索引
    int j = mid + 1;  // 右子数组的起始索引
    int k = left;     // 合并后数组的起始索引
    long long count = 0;  // 逆序对的个数
    
    // 统计逆序对的个数
    while (i <= mid && j <= right) {
        if (arr[i] > 2 * arr[j]) {
            count += (mid - i + 1);
            j++;
        } else {
            i++;
        }
    }
    
    // 归并排序并计算逆序对
    i = left;
    j = mid + 1;
    k = left;
    while (i <= mid && j <= right) {
        if (arr[i] <= arr[j]) {
            temp[k++] = arr[i++];
        } else {
            temp[k++] = arr[j++];
        }
    }
    
    while (i <= mid) {
        temp[k++] = arr[i++];
    }
    
    while (j <= right) {
        temp[k++] = arr[j++];
    }
    
    for (i = left; i <= right; i++) {
        arr[i] = temp[i];
    }
    
    return count;
}

long long mergeSort(int arr[], int temp[], int left, int right) {
    long long count = 0;
    
    if (left < right) {
        int mid = (left + right) / 2;
        
        count += mergeSort(arr, temp, left, mid);
        count += mergeSort(arr, temp, mid + 1, right);
        
        count += merge(arr, temp, left, mid, right);
    }
    
    return count;
}

int main() {
    int N;
    int arr[MAX_N];
    int temp[MAX_N];
    
    while (1) {
        // 读取输入
        scanf("%d", &N);
        if (N == 0) {
            break;
        }
        
        for (int i = 0; i < N; i++) {
            scanf("%d", &arr[i]);
        }
        
        // 使用分治技术求解逆序对个数
        long long count = mergeSort(arr, temp, 0, N - 1);
        
        // 输出结果
        printf("%lld\n", count);
    }
    
    return 0;
}

该算法使用归并排序的思想,在归并排序的过程中统计逆序对的个数。在归并的过程中,通过比较左子数组和右子数组的元素来统计逆序对的个数,并将左子数组和右子数组合并成一个有序数组。最后,返回逆序对的个数作为解。

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

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

相关文章

表面计量封闭型高斯滤波器(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

按照json文件的值复制图片

按照json文件的值复制图片 文件格式处理当前JSON代码封装增加批处理 文件格式 0是不挑选&#xff0c;1是挑选 处理当前JSON # coding: utf-8 from PIL import Image, ImageDraw, ImageFont import os import shutil import cv2 as cv import numpy as np import jsondef read…

TDesign在按钮上加入图标组件

在实际开发中 我们经常会遇到例如 添加或者查询 我们需要在按钮上加入图标的操作 TDesign自然也有预备这样的操作 首先我们打开文档看到图标 例如 我们先用某些图标 就可以点开下面的代码 可以看到 我们的图标大部分都是直接用tdesign-icons-vue 导入他的组件就可以了 而我…

【【萌新的STM32学习20--按键输入实验】】

萌新的STM32学习20–按键输入实验 在了解完蜂鸣器的实验之后我们又进行一个小实验 又是正点原子没有上课讲解的实验 对于这种不平滑的情况我们更多的也会去选择方法进行消除抖动 软件消抖&#xff1a;方法很多&#xff0c;我们例程中使用最简单的延时消抖。检测到按键按下后&…

矿业配电柜监测,真的如此难以克服?

当今工业和商业领域中&#xff0c;电力作为生产和运营的基石&#xff0c;无可替代。在这个背景下&#xff0c;配电柜监控的重要性日益凸显。 配电柜作为电力系统的核心组成部分&#xff0c;其稳定运行直接关系到生产的连续性、安全性以及能源的高效利用。通过配电柜监控&#x…

小红书爆款种草笔记拆解:如何打造吸引眼球的内容!

小红书作为一个生活方式平台和消费决策入口&#xff0c;已成为众多年轻人所喜爱的种草圣地。在这里&#xff0c;用户可以通过分享美妆、穿搭、美食等各类生活方式&#xff0c;吸引大量的关注和点赞。然而&#xff0c;如何在小红书上打造一篇吸引眼球、引发用户种草的爆款笔记呢…

每日一题 823. 带因子的二叉树

每日一题 823. 带因子的二叉树 难度&#xff1a;中等 思路&#xff1a; 取乘积&#xff0c;那么两个叶子节点相乘一定会得到一个更大的数&#xff0c;所以先排序以父节点为根节点的数的数量 以右节点为根节点的数的数量 * 以左节点为根节点的数的数量初始化列表&#xff0c;…

vscode vue3自定义自动补全

敲代码多了&#xff0c;发现重发动作很多&#xff0c;于是还是定义自动补全代码吧——懒是第一生产力&#xff01; 1&#xff0c;Ctrl Shift P打开快捷命令行&#xff1a;找到下面这个 2&#xff0c;然后找到ts&#xff1a; 里面给了demo照着写就行 // "Print to conso…

【Qt QAxObject】使用 QAxObject 高效任意读写 Excel 表

1. 用什么操作 Excel 表 Qt 的官网库中是不包含 Microsoft Excel 的操作库&#xff0c;关于对 Microsoft Excel 的操作库可选的有很多&#xff0c;包含基于 Windows 系统本身的 ActiveX、Qt Xlsx、xlsLib、LibXL、qtXLS、BasicExcel、Number Duck。 库.xls.xlsx读写平台Qt Xls…

访问学者择校容易犯哪些错误?

在选择访问学者的学校时&#xff0c;很多人容易犯一些错误&#xff0c;这些错误可能会影响他们的学术和个人发展。下面就让知识人网小编带大家一起来探讨一下&#xff0c;访问学者在选择学校时容易犯的一些错误。 首先&#xff0c;许多访问学者容易陷入排名偏见。他们可能会过于…

什么是数字化工厂呢?为何MES管理系统是工业4.0的核心

随着互联网时代的来临&#xff0c;线上业务逐渐成为企业发展的新趋势。越来越多的企业开始将业务拓展到线上&#xff0c;开展数字化工厂转型。那么&#xff0c;什么是数字化工厂呢&#xff1f;它有哪些特点呢&#xff1f; 数字化工厂&#xff0c;是指以数字化技术&#xff0c;包…

React 的七个值得推荐的动画库

今天&#xff0c;Web 应用程序用户界面有许多吸引用户的元素&#xff0c;为了满足这些需求&#xff0c;开发人员不得不寻找新的方法来实现带有动画和过渡的 UI&#xff0c;因此&#xff0c;开发了专门的库和工具来处理 Web 应用程序中的动画。在本文中&#xff0c;将讨论一些优…

Ansible学习笔记2

Ansible是Python开发的自动化运维工具&#xff0c;集合了众多运维工具&#xff08;Puppet、cfengine、chef、func、fabric&#xff09;的优点&#xff0c;实现了批量系统配置&#xff0c;批量程序部署、批量运行命令等功能。 特点&#xff1a; 1&#xff09;部署简单&#xff…

Ceph入门到精通-LVS基础知识

LB集群: &#xff08;Load Balancing&#xff09;即负载均衡集群,其目的是为了提高访问的并发量及提升服务器的性能&#xff0c;其 实现方式分为硬件方式和软件方式。 硬件实现方式&#xff1a; 常用的有 F5公司的BIG-IP系列、A10公司的AX系列、Citrix公司的 NetScaler系列…

延迟队列的理解与使用

目录 一、场景引入 二、延迟队列的三种场景 1、TTL对队列进行延迟 2、创建通用延时消息对消息延迟 3、使用rabbitmq的延时队列插件 x-delayed-message使用 父pom文件 pom文件 配置文件 config 生产者 消费者 结果 一、场景引入 我们知道可以通过TTL来对队列进行设…

百数应用中心——生产制造管理解决方案解决行业难题

传统生产制造业面临着许多挑战&#xff0c;其中一些主要问题包括效率低下、交期压力大、需求预测不准确、生产模式复杂、异常响应慢、库存高和计划脱节等。这些问题不仅影响了生产效率和质量&#xff0c;也导致了不必要的成本和客户满意度下降。 生产制造管理应用对于企业的生产…

[已解决] wget命令出现Unable to establish SSL connection.错误

问题 从win11上下载best.ckpt包时 遇到&#xff1a; Unable to establish SSL connection.错误 解决方案&#xff1a; 加上参数&#xff1a; 加上跳过验证证书的参数--no-check-certificate 有些网站不允许通过非浏览器的方式进行下载&#xff0c;使用代理既可以解决问题&am…

MES管理系统中常用的数据模型有哪些

在MES管理系统项目中&#xff0c;数据建模对于生产过程的监控、分析和管理具有至关重要的作用。本文将介绍一些常见的MES管理系统数据建模方面&#xff0c;并阐述它们在生产过程中的重要性和应用。 1、产品数据模型是MES系统中的基础模块之一。它涵盖了产品的基本信息、规格和属…

JavaScript 中的箭头函数:如何使用简洁的语法

了解有关 JavaScript 箭头函数的所有信息。我们将向您展示如何使用 ES6 箭头语法&#xff0c;以及在代码中利用箭头函数时需要注意的一些常见错误。您将看到许多示例来说明它们的工作原理。 JavaScript 箭头函数随着 ECMAScript 2015&#xff08;也称为 ES6&#xff09;的发布…

【pyqt5界面化开发-4】垂直布局/水平布局+‘套娃‘布局

目录 一、垂直布局 二、布局器的组合 三、水平布局垂直布局&#xff08;套娃&#xff09; 一、垂直布局 需要模块&#xff1a;QVBoxLayout # 垂直布局layout QVBoxLayout()………………# 应用设置的布局器self.setLayout(layout) 模块间的伸缩器&#xff08;可以理解为弹簧…