2019第十届蓝桥杯比赛总结(B组c/c++)
试题 A: 组队
本题总分:5 分
作为一位篮球队教练,在球员选拔方面你面临着一项重要的决策任务:从候选名单中分别挑选出一名1号位至5号位的球员,并为每个位置配备最优秀的选手。每位球员在其各个位置上的表现已经被详细记录在表格中,请计算所选首发球员各位置评分之和的最大可能值是多少?

题解:第一题略水,但要注意仔细读题一个队员无法被重复使用,答案490。
试题 B: 年号字串
本题总分:5 分
答案提交
答案提交
题解:进制问题,26的进制问题。自己当时反应了半天,才转过弯来。感觉自己还是太菜了。
#include<cstdio>
int main()
{
int x = 2019;
int a[10];
int k = 0;
while(x / 26 != 0)
{
a[k++] = x % 26;
x /= 26;
}
a[k++] = x;
for(int i = k - 1; i >= 0; --i)
printf("%c", a[i] + 'A' - 1);
return 0;
}
试题 C: 数列求值
本题总分:10 分
答案提交
答案提交
题解:基于基本的递推算法,在处理大数据量时需要进行取模操作以避免计算溢出问题。为了确保计算的稳定性与准确性起见, 选择将数值限定在1,00万以内, 这样即使运算过程中产生较大的中间结果也不会超出计算机处理范围;不过, 在实际应用中发现仅保留最后四位数字即可满足精度要求, 因此最终决定将数值截断至后四位。经过进一步思考发现这种方法可能并非最优选择, 经过验证得到最终的答案是4659
试题 D: 数的分解
本题总分:10 分
问题描述
答案提交
题解:做的时候,直接暴力,但是刚出来时,我也不知道答案是否正确,答案40785。
#include<cstdio>
int f(int x)
{
while(x != 0)
{
int t = x % 10;
if(t == 2 || t == 4)
return 0;
x /= 10;
}
return 1;
}
int main()
{
int sum = 0;
for(int i = 1; i <= 2019; ++i)
for(int j = i + 1; j <= 2019; ++j)
for(int k = j + 1; k <= 2019; ++k)
{
if(i + j + k == 2019 && f(i) && f(j) &&f(k))
sum++;
}
printf("%d\n", sum);
return 0;
}
试题 E: 迷宫
问题描述
题解:典型的搜索问题,在比赛中遇到这道填空题时往往耗时最长的原因之一是因为对该方法不够熟悉而犹豫不决。比赛时采用的是深度优先搜索(DFS)暴力枚举的方法。需要注意的是,在处理相同长度路径时应选择字典序最小的那个结果。为了实现这一点,方向顺序必须按照D、L、R、U的顺序排列(即上北右东下南左西)。然而,在实际编码过程中遇到了一些逻辑错误和边界条件处理不当的问题,在调试阶段花费了大量的时间才逐步修正这些问题。起初并未采用广度优先搜索(BFS)算法,并且由于时间限制未能对代码进行进一步优化以解决这些问题。最终程序运行时间过长未能得到更新的路径信息。经过多次尝试后发现仅通过DFS难以找到最优解,并最终只能根据答案推断出正确的解决方案应为使用BFS算法而非DFS算法
dfs错误代码:
#include<cstdio>
int to[4][2] = {1, 0, 0, -1, 0, 1, -1, 0};//字典序最小
char ans[15000];
int Min = 1000000;
char m[30][51];
void dfs(int x, int y, int num, char t[])
{
// printf("%d %d\n", x, y);
if(x == 29 && y == 49 && Min > num)
{
Min = num;
t[num] = '\0';
printf("%s\n\n\n", t);
return;
}
for(int i = 0; i < 4; ++i)
{
int dx = x + to[i][0];
int dy = y + to[i][1];
if(m[dx][dy] == '0' && dx >= 0 && dx < 30 && dy >= 0 && dy < 50)
{
if(i == 0)
t[num] = 'D';
else if(i == 1)
t[num] = 'L';
else if(i == 2)
t[num] = 'R';
else
t[num] = 'U';
num++;
m[dx][dy] = '1';
dfs(dx, dy, num, t);//试探
m[dx][dy] = '0';
num--;//回溯
}
}
}
int main()
{
for(int i = 0; i < 30; ++i)
scanf("%s", m[i]);
char t[150000];
dfs(0, 0, 0, t);
return 0;
}
bfs正确代码:
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int maxn = 100;
char s[maxn][maxn];
int vis[maxn][maxn];
int dir[4][2] = {1,0, 0, -1, 0, 1, -1, 0};
char map[5] = "DLRU";
void dfs(int x, int y){
if(vis[x][y]==-2){
return ;
}
dfs(x-dir[vis[x][y]][0], y-dir[vis[x][y]][1]);
printf("%c", map[vis[x][y]]);
}
int main(){
memset(vis, -1, sizeof(vis));
int n = 30, m = 50;
for(int i = 1; i <= n; i++) scanf("%s", s[i]+1);
vis[1][1] = -2;
queue<pair<int, int> > q;
q.push(make_pair(1, 1));
while(!q.empty()){
pair<int, int> k = q.front();
q.pop();
for(int i = 0; i < 4; i++){
int x = k.first+dir[i][0], y = k.second+dir[i][1];
if(x <= 0 || x > n || y <= 0 || y > m || vis[x][y]!=-1 || s[x][y]=='1') continue;
vis[x][y] = i;
q.push(make_pair(x, y));
}
}
dfs(n, m);/*这里只是用dfs打印一下路径。核心还是bfs,一开始没选择bfs就是不知道如何打印路径,还有就是bfs快遗忘完了。这是网上大佬的方法。*/
return 0;
}
德氧核苷酸序列表现为连续重复片段如DDD...等
试题 F: 特别数的和
问题描述
题解:编程第一题,简单粗暴没啥坑。按着题意写就ok了。
#include<iostream>
#include<cstdio>
using namespace std;
bool check(int x){
while(x){
if(x%10==0 || x%10==2 || x%10==1 || x%10==9) return true;
x/=10;
}
return false;
}
int main(){
int n, ans = 0;
scanf("%d", &n);
for(int i = 1; i <= n; i++){
if(check(i)) ans+=i;
}
printf("%d\n", ans);
return 0;
}
总结:尚未获取到后几道题的详细解答,并且对于自己解答的正确性也无法判断。计划在日后专门整理和更新这些内容以供参考。这也是我首次参与蓝桥杯竞赛,在此分享基于个人体验归纳的几点经验。
蓝桥杯确实让人头疼的一点是所有比赛的结果往往在成绩公布后才会知晓。因此,在比赛中保持高度的专注力和细致观察是至关重要的策略。
2.时间分配要合理,填空题不要纠结太久,多留点时间做编程题。
建议在编程题测试中多测试几组数据,并涵盖所有可能的情况。观察他提供的数据范围后会发现其中隐藏了很多潜在的问题。
虽然两者都属于编程类竞赛。相较于同级别的ACM比赛而言,蓝桥杯整体上更加轻松愉快。大都情况下参赛者都能够完成大部分题目,并且这些题目都比较容易上手。都能够通过基础测试数据并获得部分分数。但尽管如此我还是特别享受解出ACM难题时的那种满足感和成就感。
