蓝桥杯C++组怒刷50道真题(填空题)
🌼深夜伤感网抑云 - 南辰Music/御小兮 - 单曲 - 网易云音乐
🌼多年后再见你 - 乔洋/周林枫 - 单曲 - 网易云音乐
18~22年真题,50题才停更,课业繁忙,有空就更,2023/3/18/23:01写下
目录
👊填空题
🌼一,[蓝桥杯2020初赛] 门牌制作
🌼二,[蓝桥杯2020初赛] 既约分数
🌼三,[蓝桥杯2020初赛] 蛇形填数
🌼四,[蓝桥杯2020初赛] 七段码
🌼五,[蓝桥杯2020初赛] 约数个数
🌼六,[蓝桥杯2021初赛] 卡片
🌼七,[蓝桥杯2021初赛] 直线
🌼八,[蓝桥杯2021初赛] 货物摆放
🌼九,[蓝桥杯2021初赛] 路径
🌳Floyd-Warshall
🌳Dijkstra AC
🌼十, [蓝桥杯2021初赛] 空间
🌼十一,[蓝桥杯2022初赛] 裁纸刀
🌼十二,[蓝桥杯2022初赛] 灭鼠先锋
🌼十三, [蓝桥杯2022初赛] 九进制转十进制
🌼十四, [蓝桥杯2022初赛] 顺子日期
🌼十五,[蓝桥杯2022初赛] 排列字母
🌼十六,[蓝桥杯2019初赛]平方和
🌼十七,[蓝桥杯2019初赛]数列求值
🌼十八,[蓝桥杯2019初赛]最大降雨量
🌼十九,1455: [蓝桥杯2019初赛]迷宫
🌳BFS一 AC
🌳BFS二 AC
🌼二十,1462: [蓝桥杯2019初赛]组队
🌳观察法
🌳DFS
🍉🍉🍉🍉🍉🍉🍉🍉🍉🍉🍉
👊填空题总结
⚠注意!!!编程题和填空题分成两个博客,毕竟50题,少说5万字,边敲边发布会很卡
编程题链接: (未完待续)
-------------------------------------------------------
-------------------------------------------------------
👂 空 清新民谣版 - 汪小敏 - 单曲 - 网易云音乐
骗分过样例,暴力出奇迹;暴搜挂着机,打表出省一 (过去式了,看22年A组就知道)
2018,2019,2020,2021,2022年蓝桥杯C++/C组省赛A,B,G组真题
题目链接,题目, 解析,代码
要参加2023年C++组A组省赛了!希望可以省一,没有也不要紧,还有大二
当然,如果题目不对胃口,有些ACM银牌的大佬也才省二...对头的话,打铁选手也给你来个国一国二
和我一起刷进蓝桥杯C++A组省一(小声)
👊填空题
咱先从20年开始
🌼一,[蓝桥杯2020初赛] 门牌制作
P1508 - [蓝桥杯2020初赛] 门牌制作 - New Online Judge (ecustacm.cn)
考虑到蓝桥杯OI赛制(没有反馈),最好自己多试几组例子,比如我,将代码第6行 i <= 2020分别改成23, 1, 19, 32测试了下,如果和草稿本算的一样,就算过了
否则真到比赛时信心满满,感觉自己AC了七八道题,最后连个省二都没就笑了
#include<iostream>
using namespace std;
int main()
{int sum = 0, j;for(int i = 1; i <= 2020; ++i) {j = i;while(j / 10) {if(j % 10 == 2)sum += 1;j /= 10;}if(j % 10 == 2) sum += 1;}cout<<sum;return 0;
}
624
🌼二,[蓝桥杯2020初赛] 既约分数
P1509 - [蓝桥杯2020初赛] 既约分数 - New Online Judge (ecustacm.cn)
用辗转相除法求最大公约数
原理: 原来的除数(➗右边的) / 余数
1997 ÷ 615 = 3 (余 152)
615 ÷ 152 = 4(余7)
152 ÷ 7 = 21(余5)
7 ÷ 5 = 1 (余2)
5 ÷ 2 = 2 (余1)
2 ÷ 1 = 2 (余0)
至此,最大公约数为1
#include<iostream>
using namespace std;
int com(int x, int y)
{while(x % y) { //辗转相除法int z = x % y;x = y;y = z;}return y;
}
int main()
{int sum = 0;for(int i = 1; i <= 2020; ++i)for(int j = 1; j <= 2020; ++j)if(com(i, j) == 1) sum++;cout<<sum;return 0;
}
2481215
🌼三,[蓝桥杯2020初赛] 蛇形填数
P1510 - [蓝桥杯2020初赛] 蛇形填数 - New Online Judge (ecustacm.cn)
容易发现,数字按照 右-->左下-->下-->右上 的规律递增
加个判断边界的条件即可
先画到45,可知,找第n行n列, i, j 需要遍历到2 * n - 1
#include<iostream>
using namespace std;
int a[1000][1000];
int main()
{a[1][1] = 1;int m = 1;for(int i = 1, j = 1; i <= 40 && j <= 40;) {//右a[i][++j] = ++m;//左下while(1) {a[++i][--j] = ++m;if(j == 1) break;}//下a[++i][j] = ++m;//右上while(1) {a[--i][++j] = ++m;if(i == 1) break;}}cout<<a[20][20];return 0;
}
761
🌼四,[蓝桥杯2020初赛] 七段码
P1511 - [蓝桥杯2020初赛] 七段码 - New Online Judge (ecustacm.cn)
第一次做,猜了63种,错了,7 + 10 + 14 + 14 + 10 + 7 + 1 = 63
错在哪里呢,错在3,4,5段发光
而且由于不发光部分不需要连通,所以 3段 != 4段, 2段 != 5段
这道题单靠猜,90%的人都做不对,很容易就漏掉几种或者想当然
当然代码我也不会😂
来个别人的AC代码把
#include <stdio.h>
#include <stdlib.h>int main(int argc, char *argv[])
{// 请在此输入您的代码int sum = 0;//有一段二极管发光; a,b,c,d,e,f,gint l1 = 7;//有两段二极管发光; ab,af,bc,bg,cg,cd,de,eg,ef,fgint l2 = 10;//有三段二极管发光; abf,abc,abg,afg,afe,bcd,bcg,bgf,bge,cgd,cgf,cge,cde,cdg,deg,def,efgint l3 = 16;////有四段二极管发光; abcd,abcg,abcf,abge,abgf,abfe,afeg,bcde,bcdg,bcgf,bcge,bged,bgef,cdef,cdeg,cdgf,cgfa,cgfe,defg,defaint l4 = 20;//有五段二极管发光即有两端不发光; ab,ac,ad,ae,af,ag,bc,bd,be,bg,cd,cf,cg,de,df,dg,ef,eg,fgint l5 = 19;////有六段二极管发光即有一端不发光; a,b,c,d,e,f,gint l6 = 7;//(找一段二极管不发光的:)//第七种情况,全部发光int l7 = 1;sum = l1 + l2 + l3 + l4 + l5 + l6 + l7;printf("%d\n", sum);return 0;
}
🌼五,[蓝桥杯2020初赛] 约数个数
P1514 - [蓝桥杯2020初赛] 约数个数 - New Online Judge (ecustacm.cn)
#include<iostream>
using namespace std;
int main()
{int sum = 0;for(int i = 1; i <= 1200000; ++i)if(1200000 % i == 0) sum++;cout<<sum;return 0;
}
96
到21年
🌼六,[蓝桥杯2021初赛] 卡片
P1550 - [蓝桥杯2021初赛] 卡片 - New Online Judge (ecustacm.cn)
初始化a[10]为2021,对应着0~9,int k = i; a[k % 10]--即可
但是有个问题,代码虽然输出了正确答案,但是提交时显示编译错误,原来是语言选了C
#include<iostream>
using namespace std;
int a[10];
int main()
{for(int i = 0; i <= 9; ++i)a[i] = 2021; //初始化int flag = 0;for(int i = 1;; ++i) { //从1开始遍历int k = i;while(k) {a[k % 10]--;k /= 10;}for(int j = 0; j <= 9; ++j)if(a[j] < 0) {cout<<i - 1;flag = 1; //到头了break;}if(flag) break;}return 0;
}
3181
🌼七,[蓝桥杯2021初赛] 直线
P1551 - [蓝桥杯2021初赛] 直线 - New Online Judge (ecustacm.cn)
注意,除了下标和计数的now,其他都声明为double
而且第一次看成斜率相同算同一条直线了...
如果只是判断多少种斜率,最简单的set即可
但这里斜率 + 截距才能确定一条直线
一开始...犯了个重名的小错误, 找了半小时 + 百度 才找出来...
set<pair<double, double>>b; //斜率k, 截距bfor(int i = 0; i < 420; ++i)for(int j = 0; j < 420; ++j) {if(a[i].x != a[j].x && a[i].y != a[j].y) {double k = (a[i].y - a[j].y) / (a[i].x - a[j].x);double b = a[i].y - k * a[i].x;b.insert({k, b});}}
报错error: request for member 'insert' in 'b', which is of non-class type 'double'
意思是, set变量名b和循环里面的double b重复了
修改后,第一次提交, 错了....(原因会在后面分析)
错误代码
#include<iostream>
#include<set> //set<>b;
using namespace std;
struct place
{double x, y; //横纵坐标
};
int main()
{struct place a[430];int now = 0;//读入420个点for(double i = 0; i <= 19; ++i)for(double j = 0; j <= 20; ++j) {a[now].x = i;a[now++].y = j;}//判断不同的直线set<pair<double, double>>line; //斜率k, 截距bfor(int i = 0; i < 420; ++i)for(int j = 0; j < 420; ++j) {if(a[i].x != a[j].x && a[i].y != a[j].y) {double k = (a[i].y - a[j].y) / (a[i].x - a[j].x);double b = a[i].y - k * a[i].x;line.insert({k, b});}}cout<<line.size() + 20 + 21; //加上竖和横return 0;
}
48953
而正确答案是40257
错误原因是double精度丢失
k那里没问题, 问题是b那里,解决方案是
b = y1 - (y2 - y1) / (x2 - x1) * x1 ----> b = (y1 * (x2 - x1) - (y2 - y1) * x1) / (x2 - x1)
猜测是先除再减,会丢失更多精度....
AC代码
当然,我用结构体写的有点乱了,意思就是这么个意思, y = kx + b, k = (y2 - y1) / (x2 - x1)
核心思路就是斜率和截距确定一条直线 + set排除重合元素 + pair
#include<iostream>
#include<set> //set<>b;
using namespace std;
struct place
{double x, y; //横纵坐标
};
int main()
{struct place a[430];int now = 0;//读入420个点for(double i = 0; i <= 19; ++i)for(double j = 0; j <= 20; ++j) {a[now].x = i;a[now++].y = j;}//判断不同的直线set<pair<double, double>>line; //斜率k, 截距bfor(int i = 0; i < 420; ++i)for(int j = 0; j < 420; ++j) {if(a[i].x != a[j].x && a[i].y != a[j].y) { //排除横竖直线double k = (a[i].y - a[j].y) / (a[i].x - a[j].x);double b = (a[i].y * (a[i].x - a[j].x) -(a[i].y - a[j].y) * a[i].x) / (a[i].x - a[j].x);line.insert({k, b});}}cout<<line.size() + 20 + 21; //加上竖和横return 0;
}
40257
🌼八,[蓝桥杯2021初赛] 货物摆放
P1552 - [蓝桥杯2021初赛] 货物摆放 - New Online Judge (ecustacm.cn)
虽然填空题不看复杂度,但是这么大的数,直接O(n^3)暴力肯定不行
容易发现,虽然是三个数,还是能用找因子的方法,用一个数组保存因子即可
因子用取余 == 0的方式判断
第一次敲完, 输出0.....然后一看int a[10000]里,单个数不能超过int,所以改long long就好了
#include<iostream>
#include<cmath> //sqrt()
using namespace std;
long long a[10010];
int main()
{long long n = 2021041820210418, sum = 0, now = 0;for(long long i = 1; i < sqrt(n); ++i)if(n % i == 0) { //找出因子a[now++] = i;if(i * i != n) //判断另一个因子a[now++] = n / i;}for(int i = 0; i < now; ++i)for(int j = 0; j < now; ++j)for(int k = 0; k < now; ++k)if(a[i] * a[j] * a[k] == n) sum++;cout<<sum;return 0;
}
2430
🌼九,[蓝桥杯2021初赛] 路径
P1553 - [蓝桥杯2021初赛] 路径 - New Online Judge (ecustacm.cn)
看到最短路, 正好前天刚学了Floyd-Warshall和Dijkstra , 盘它
不会的可以看看这个博客
(5条消息) 最短路之Floyd-Warshall(10张图解)_码龄11天的博客-CSDN博客
(2条消息) 最短路之Dijkstra(15张图解)_迪杰斯特拉算法求最短路径图解_码龄?天的博客-CSDN博客
1,floyd是求多源最短路的
而且Floyd和Dijkstra都适用于稠密图(本题显然是稠密图)
假设n个顶点, m条边
看到没,这个才是稠密图(m >= n^2)
而一般的10个顶点,20条边这种,都是稀疏图(m << n^2)
Floyd核心思路还是中转
2,将"路"读入二维数组e;
3,第三个我们借辗转相除法间接求出最小公倍数
第一次敲完,无论是顶点1到2021还是顶点1到100,输出都是1e8,肯定哪里错了
然后我对每一部分进行验算
1,求公倍数函数com()没问题
2,Floyd那里有问题
//利用中转求最短路
for(int k = 1; k <= 2021; ++k) //通过所有点中转if(e[1][k] + e[k][2021] < e[1][2021])
为什么这段代码会让每次都输出无穷值呢?
因为你误以为Floyd可以求单源最短路. 它必须先通过求出多源最短路,才能找到单源的答案
只能用n^3先算出所有点的最短路,才能求1到2021的最短路
🌳Floyd-Warshall
(本地AC, OJ上时间超限)
#include<iostream>
#include<cmath> //abs()
using namespace std;
int e[2050][2050];
int inf = 1e9; //infinity无穷int com(int x, int y)
{int a = x, b = y;while(y) {int z = x % y;x = y;y = z; //最后的x为公因数}return a * b / x; //最小公倍数
}int main()
{//初始化for(int i = 1; i <= 2021; ++i)for(int j = 1; j <= 2021; ++j) {if(i == j) e[i][j] = 0; //自己到自己距离为0else e[i][j] = inf;}//读入边的长度for(int i = 1; i <= 2021; ++i)for(int j = 1; j <= 2021; ++j) {if(abs(i - j) <= 21 && i != j) {e[i][j] = com(i, j);e[j][i] = e[i][j]; //无向边}}//利用中转求最短路(Floyd核心)for(int k = 1; k <= 2021; ++k) //通过所有点中转for(int i = 1; i <= 2021; ++i)for(int j = 1; j <= 2021; ++j)if(e[i][k] + e[k][j] < e[i][j])e[i][j] = e[i][k] + e[k][j];cout<<e[1][2021];return 0;
}
等了10秒才出结果(不要提交这个,这个在本地算出答案,只提交答案即可)
10266837
提交时,怕超时,所以直接printf()
AC代码
#include<iostream>
using namespace std;
int main()
{cout<<10266837;return 0;
}
尽管时间复杂度达O(n^3), 大约是(2*10^3)^3 = 8e9, 也不是很大,毕竟顶点个数才2021个
所以填空题,一般建议暴力解决 + printf()
------------------------------------------------------------------
下面,我再用Dijkstra做下这题
Dijkstra的科普博客(6条消息) 最短路之Dijkstra(15张图解)_码龄11天的博客-CSDN博客
Dijkstra原理是贪心,而Floyd是动态规划
1,初始化数组
2,循环
(1)确定源点到最近点的最短路径
(2)从刚被确定的点"出边"
🌳Dijkstra AC
#include<iostream>
#include<cmath> //abs()
using namespace std;
int e[2050][2050], dis[2050], book[2050];
int inf = 1e9; //infinity无穷int com(int x, int y)
{int a = x, b = y;while(y) {int z = x % y;x = y;y = z; //最后的x为公因数}return a * b / x; //最小公倍数
}
int main()
{//初始化for(int i = 1; i <= 2021; ++i)for(int j = 1; j <= 2021; ++j) {if(i == j) e[i][j] = 0; //自己到自己距离为0else e[i][j] = inf;}//读入边的长度for(int i = 1; i <= 2021; ++i)for(int j = 1; j <= 2021; ++j) {if(abs(i - j) <= 21 && i != j) {e[i][j] = com(i, j);e[j][i] = e[i][j]; //无向边}}//初始化book和dis数组for(int i = 1; i <= 2021; ++i) {book[i] = 0;dis[i] = e[1][i];}//Dijkstrafor(int i = 1; i <= 2020; ++i) { //n - 1次确定最短路int Min = inf;int u;//找确定值for(int j = 2; j <= 2021; ++j) { //1为源点,从下一个开始if(book[j] == 0 && dis[j] < Min) {Min = dis[j];u = j;}}book[u] = 1; //源点1号到u号的距离确定为最短路程//从刚确定的点出边for(int k = 2; k <= 2021; ++k) {//两点连通且可更新if(e[u][k] < inf && dis[k] > dis[u] + e[u][k])dis[k] = dis[u] + e[u][k];}}cout<<dis[2021];return 0;
}
10266837
时间复杂度O(n^2),2021个点的数据量,直接提交也能过了
🌼十, [蓝桥杯2021初赛] 空间
P1555 - [蓝桥杯2021初赛] 空间 - New Online Judge (ecustacm.cn)
一个32位二进制整数 = 4B, 1KB = 1024B, 1MB = 1024KB
所以 256MB = 256 * 1024 * 1024 / 4 个32位二进制整数
#include<iostream>
using namespace std;
int main()
{cout<<256 * 256 * 1024;return 0;
}
到22年了
🌼十一,[蓝桥杯2022初赛] 裁纸刀
P2021 - [蓝桥杯2022初赛] 裁纸刀 - New Online Judge (ecustacm.cn)
🌼十二,[蓝桥杯2022初赛] 灭鼠先锋
P2022 - [蓝桥杯2022初赛] 灭鼠先锋 - New Online Judge (ecustacm.cn)
22年A组前两道填空题,放个以前的博客👇
(8条消息) 2022蓝桥杯省赛C++A组初尝试_码龄11天的博客-CSDN博客
🌼十三, [蓝桥杯2022初赛] 九进制转十进制
P2031 - [蓝桥杯2022初赛] 九进制转十进制 - New Online Judge (ecustacm.cn)
先让我们回忆下,十六进制转10怎么转的?
首先作为字符串输入 ,如果由0~9组成的十六进制数, 只需
if(s[i] >= '0' && s[i] <= '9') sum += s[i] - '0';
......
sum *= 16;
接下来有样学样就行,关键别人还给了确定的数
2022(9) = 2 * 9^0 + 2 * 9^1 + 0 * 9^2 + 2 * 9^3
#include<iostream>
using namespace std;
int main()
{int sum = 2 * 1 + 2 * 9 + 0 + 2 * 9*9*9;cout<<sum;return 0;
}
粗心就会败北,第一次提交还写错个1,,,,真到蓝桥杯,一定要细心细心再细心
在草稿纸列清楚条条框框和细节,想尽可能多的, 特殊的样例
🌼十四, [蓝桥杯2022初赛] 顺子日期
P2032 - [蓝桥杯2022初赛] 顺子日期 - New Online Judge (ecustacm.cn)
一开始我以为是任意年份,,,写了一堆字符串验证
然后看到了2022
先梳理思路,2022肯定构不成顺子,如果最后一个2开始构成顺子,2,3,4,需要第34月
也不可能
细心细心再细心,不要想当然,老老实实列出所有情况
所以只能从月,日入手:
1,01月 + 20~29日(10种)
2,10月 + 12日(1种)
3,11月 + 23日(1种)
4,12月 + 30~31日 (2种)
10 + 1 + 1 + 2 = 14
#include<iostream>
using namespace std;
int main()
{ cout<<14;return 0;
}
细心的人,高考能拿多50分;而粗心,足以使一个国二变成省二
🌼十五,[蓝桥杯2022初赛] 排列字母
P2041 - [蓝桥杯2022初赛] 排列字母 - New Online Judge (ecustacm.cn)
标签:入门题,模拟
按字符数组输入字符串,strlen()求字符数组字符串长度,sort()排序
#include<iostream>
#include<algorithm> //sort()
#include<cstring> //strlen()
using namespace std;
int main()
{char s[20200] = "WHERETHEREISAWILLTHEREISAWAY";sort(s, s + strlen(s));cout<<s;return 0;
}
AAAEEEEEEHHHIIILLRRRSSTTWWWY
当然,这种填空题,自己直接排序,敲上去printf()也可
🌼十六,[蓝桥杯2019初赛]平方和
P1452 - [蓝桥杯2019初赛]平方和 - New Online Judge (ecustacm.cn)
#include<iostream>
typedef long long LL;
using namespace std;
bool check(LL n)
{while(n) {LL m = n % 10;if(m == 0 || m == 1 || m == 2 || m == 9)return true;n /= 10;}return false;
}
int main()
{LL sum = 0;for(LL i = 1; i <= 2019; ++i) {if(check(i))sum += i * i;}cout<<sum;return 0;
}
2658417853
当然,最后提交时,我是这样提交的
#include <iostream>
using namespace std;
int main()
{cout<<2658417853;return 0;
}
🌼十七,[蓝桥杯2019初赛]数列求值
P1453 - [蓝桥杯2019初赛]数列求值 - New Online Judge (ecustacm.cn)
第一次,求出0115,做错了。。
错误代码
#include<iostream>
typedef long long LL;
using namespace std;
LL a[20200000];
int main()
{a[1] = 1; a[2] = 1; a[3] = 1;for(int i = 4; i <= 20190324; ++i) {a[i] = a[i - 1] + a[i - 2] + a[i - 3];}cout<<a[20190324];return 0;
}
5268603393216230115
难道是超限了?应该是,考虑到题目说只需要最后四项,因为边取余边加不影响取余结果
所以我们在每一步加上取余10000
所以以后遇到,累乘或累加求最后几位数字的,每算一步取余一次
因为边加边取余,或者边乘边取余,结果不变
#include<iostream>
typedef long long LL;
using namespace std;
LL a[20200000];
int main()
{a[1] = 1; a[2] = 1; a[3] = 1;for(int i = 4; i <= 20190324; ++i) {a[i] = (a[i - 1] + a[i - 2] + a[i - 3]) % 10000; //注意这里}cout<<a[20190324];return 0;
}
4659
AC代码
#include <iostream>
using namespace std;
int main()
{cout<<4659;return 0;
}
🌼十八,[蓝桥杯2019初赛]最大降雨量
P1454 - [蓝桥杯2019初赛]最大降雨量 - New Online Judge (ecustacm.cn)
这是一道考研细心的题
审题一定要认真啊。。。
🌳Wrong Answer
读题时就感觉最大值是多少有点怪怪的,但没有细想,我把最大“降雨量”求出来不就完了?
所以,读题时感觉怪怪的地方,一定要多读几遍
搞清楚题目问的是什么,具体过程是什么
要亲自模拟一遍
如上图,这种情况降雨量最大,先草稿本算一遍,再代码来一次,一样,信心慢慢提交
#include<iostream>
using namespace std;
int main()
{int ans = 0;for(int i = 22; i <= 46; i += 4)ans += i;cout<<ans;return 0;
}
238
Wa!
🌳Accepted
看清楚,你所求出的238是最大的能量和,而降雨量为7周能量中位数,所以是34
#include<iostream>
using namespace std;
int main()
{cout<<"34";return 0;
}
🌼十九,1455: [蓝桥杯2019初赛]迷宫
P1455 - [蓝桥杯2019初赛]迷宫 - New Online Judge (ecustacm.cn)
这里介绍两种获得文件数据的方法
文件数据 oj.ecustacm.cn/upload/file/20200122/20200122134020_61830.txt
分析
⚠ 最短路杜绝dfs,指数级复杂度
下面针对是否读文件的2种情况,用bfsAC(01方阵最短路一般用bfs)
→ (5条消息) 《啊哈算法第四章之bfs》(17张图解)_千帐灯无此声的博客-CSDN博客
当然,由于填空题不考察时间复杂度(最后printf就行)所以一开始我还考虑了dijstra和Floyd
但这是01最短路,边权为1的地图,考虑bfs的模拟过程,显然bfs最合适
而Dij和Floy,做边权不为1的更合适
考察
1,读取数据
for(int i=0;i<n;i++)cin>>maze[i];
考虑到字符串按换行区分,整块粘贴过去就行
2,BFS模板,这个都要会
3,如何得到路径,网上搜了下看不懂(或者说懒得看了)
用自认为简单易懂的方式写了个(解释在注释里)
1,不用读文件
🌳BFS一 AC
我习惯用用数组模拟队列,就不用stl的queue了
关于输出路径,有个坑,第一次我少输出了第一步的D,因为最后得到路径写成这样了
while(que[tail].f) {ans += que[tail].al; //字符的连接tail = que[tail].f; //更新队尾为上一个点}
至于为什么会少输出第一步呢,请看图
假设最短路径为(1, 1), (2, 1), (3, 1), (4, 1),假设此时来到(3, 1)
于是字符串ans加上了(到达(3, 1) 需要走的)方向,然后tail = (2, 1)所代表的下标(父坐标)
此时的que[tail].f 就已经是第一个点的下标了,在代码中也就是0,所以会漏了第一步
修改
while(que[tail].f) --> while(tail)
原始代码
然而直接提交显示答案错误(超时是不可能超时的),因为本题没有输入,它的本意就是考察读取文件数据传入字符变量
#include<iostream>
using namespace std;
int tx, ty, flag, vis[100][100];
string maze[30], ans;
struct node
{ //只要求输出最短路的路线,不要求输出具体步数,不用sint x, y, f; //横坐标, 纵坐标, 父坐标char al; //方向字母
};
int main()
{for(int i = 0; i < 30; ++i)cin>>maze[i];struct node que[1510]; //30 * 50//方向数组, 由于D<L<R<U, 需要按这个顺序int next[4][2] = {{1,0},{0,-1},{0,1},{-1,0}};char dir[4] = {'D','L','R','U'}; //方向字母//初始化队列int head = 0, tail = 0;//队列插入迷宫入口坐标que[tail].x = 0;que[tail].y = 0;que[tail].f = 0;que[tail].al = '0';tail++;//队列不为空while(head < tail) {//枚举4个方向for(int i = 0; i < 4; ++i) {//新的坐标tx = que[head].x + next[i][0];ty = que[head].y + next[i][1];//超出范围if(tx < 0 || ty < 0 || tx >= 30 || ty >= 50)continue;//未访问过且不为障碍if(vis[tx][ty] == 0 && maze[tx][ty] == '0') {vis[tx][ty] = 1; //标记que[tail].x = tx;que[tail].y = ty;que[tail].f = head;que[tail].al = dir[i];tail++;//BFS不需要取消标记, 只入队1次}//到达终点if(tx == 29 && ty == 49) {flag = 1;break;}}if(flag) break;head++; //后续点的扩展}//用ans字符串保存从尾到头输出的路径tail--; //最后的tail是队尾下一个,所以-1while(tail) {ans += que[tail].al; //字符的连接tail = que[tail].f; //更新队尾为上一个点}for(int i = ans.size() - 1; i >= 0; --i)cout<<ans[i];return 0;
}
直接将输出的答案复制,cout就好,所以填空题尽量本地DevC++得到答案后,再专门cout吧
貌似填空题一般也没有输入,只有输出
输入输出
11001000110101000010101100011010011010101011110111
00011011010101001001001010000001000101001110000000
10100000101000100110101010111110011000010000111010
00111000001010100001100010000001000101001100001001
11000110100001110010001001010101010101010001101000
00010000100100000101001010101110100010101010000101
11100100101001001000010000010101010100100100010100
00000010000000101011001111010001100000101010100011
10101010011100001000011000010110011110110100001000
10101010100001101010100101000010100000111011101001
10000000101100010000101100101101001011100000000100
10101001000000010100100001000100000100011110101001
00101001010101101001010100011010101101110000110101
11001010000100001100000010100101000001000111000010
00001000110000110101101000000100101001001000011101
10100101000101000000001110110010110101101010100001
00101000010000110101010000100010001001000100010101
10100001000110010001000010101001010101011111010010
00000100101000000110010100101001000001000000000010
11010000001001110111001001000011101001011011101000
00000110100010001000100000001000011101000000110011
10101000101000100010001111100010101001010000001000
10000010100101001010110000000100101010001011101000
00111100001000010000000110111000000001000000001011
10000001100111010111010001000110111010101101111000
DDDDRRURRRRRRDRRRRDDDLDDRDDDDDDDDDDDDRDDRRRURRUURRDDDDRDRRRRRRDRRURRDDDRRRRUURUUUUUUULULLUUUURRRRUULLLUUUULLUUULUURRURRURURRRDDRRRRRDDRRDDLLLDDRRDDRDDLDDDLLDDLLLDLDDDLDDRRRRRRRRRDDDDDDRR
AC 代码
#include<iostream>
using namespace std;
int main()
{cout<<"DDDDRRURRRRRRDRRRRDDDLDDRDDDDDDDDDDDDRDDRRRURRUURRDDDDRDRRRRRRDRRURRDDDRRRRUURUUUUUUULULLUUUURRRRUULLLUUUULLUUULUURRURRURURRRDDRRRRRDDRRDDLLLDDRRDDRDDLDDDLLDDLLLDLDDDLDDRRRRRRRRRDDDDDDRR";return 0;
}
2,读文件
🌳BFS二 AC
读入文件只需要增加这些操作
maze.txt要和代码文件在同一目录下
#include<fstream>
...
//读取文件数据ifstream infile("maze.txt"); //打开maze.txt文件//按行读入maze.txt文件的字符串, 保存到maze数组中for(int i = 0; i < 30; ++i)getline(infile, maze[i]);
👆
原始代码
#include<iostream>
#include<fstream>
using namespace std;
int tx, ty, flag, vis[100][100];
string maze[30], ans;
struct node
{ //只要求输出最短路的路线,不要求输出具体步数,不用sint x, y, f; //横坐标, 纵坐标, 父坐标char al; //方向字母
};
int main()
{//读取文件数据ifstream infile("maze.txt"); //打开maze.txt文件//按行读入maze.txt文件的字符串, 保存到maze数组中for(int i = 0; i < 30; ++i)getline(infile, maze[i]);struct node que[1510]; //30 * 50//方向数组, 由于D<L<R<U, 需要按这个顺序int next[4][2] = {{1,0},{0,-1},{0,1},{-1,0}};char dir[4] = {'D','L','R','U'}; //方向字母//初始化队列int head = 0, tail = 0;//队列插入迷宫入口坐标que[tail].x = 0;que[tail].y = 0;que[tail].f = 0;que[tail].al = '0';tail++;//队列不为空while(head < tail) {//枚举4个方向for(int i = 0; i < 4; ++i) {//新的坐标tx = que[head].x + next[i][0];ty = que[head].y + next[i][1];//超出范围if(tx < 0 || ty < 0 || tx >= 30 || ty >= 50)continue;//未访问过且不为障碍if(vis[tx][ty] == 0 && maze[tx][ty] == '0') {vis[tx][ty] = 1; //标记que[tail].x = tx;que[tail].y = ty;que[tail].f = head;que[tail].al = dir[i];tail++;//BFS不需要取消标记, 只入队1次}//到达终点if(tx == 29 && ty == 49) {flag = 1;break;}}if(flag) break;head++; //后续点的扩展}//用ans字符串保存从尾到头输出的路径tail--; //最后的tail是队尾下一个,所以-1while(tail) {ans += que[tail].al; //字符的连接tail = que[tail].f; //更新队尾为上一个点}for(int i = ans.size() - 1; i >= 0; --i)cout<<ans[i];return 0;
}
当然,最后提交还是要这个,因为蓝桥杯OJ不包含maze.txt这个文件
#include<iostream>
using namespace std;
int main()
{cout<<"DDDDRRURRRRRRDRRRRDDDLDDRDDDDDDDDDDDDRDDRRRURRUURRDDDDRDRRRRRRDRRURRDDDRRRRUURUUUUUUULULLUUUURRRRUULLLUUUULLUUULUURRURRURURRRDDRRRRRDDRRDDLLLDDRRDDRDDLDDDLLDDLLLDLDDDLDDRRRRRRRRRDDDDDDRR";return 0;
}
🌼二十,1462: [蓝桥杯2019初赛]组队
P1462 - [蓝桥杯2019初赛]组队 - New Online Judge (ecustacm.cn)
team.txt链接 oj.ecustacm.cn/upload/file/20200122/20200122152423_34129.txt
思路
有点类似全排列,给定5个盒子,每个盒子一个数字,求最大的和
用dfs好了
当然,5 * 20这么点数据,100个数,一个一个数也给它数出来了
如果是50 * 50的数据量可能就算了
🌳观察法
注意,一个人只能同时打一个位置
我把每一列最高分的2~3个标记出来,如果某个队员只在唯一一个位置最高分,就选这个队员
当然,观察可知,17号选3号位的99分 或者 1号位的98分 是等价的
98 + 99 + 98 + 97 + 98 = 490
#include<iostream>
using namespace std;
int main()
{cout<<490;return 0;
}
🌳DFS
1,数据直接复制到代码里
这种办法还行,就是加 ',' 有些烦,注意还得删去第一列的编号
#include<iostream>
using namespace std;
int book[30], ans; //book[]的大小要大于20
int c[20][5] = {
{97, 90, 0 ,0, 0},
{92, 85, 96, 0, 0},
{0, 0, 0, 0, 93},
{0, 0, 0, 80, 86},
{89, 83, 97, 0, 0},
{82, 86, 0, 0, 0},
{0, 0, 0, 87, 90},
{0, 97, 96, 0, 0},
{0, 0, 89, 0, 0},
{95, 99, 0, 0, 0},
{0, 0, 96, 97, 0},
{0, 0, 0, 93, 98},
{94, 91, 0, 0, 0},
{0, 83, 87, 0, 0},
{0, 0, 98, 97, 98},
{0, 0, 0, 93, 86},
{98, 83, 99, 98, 81},
{93, 87, 92, 96, 98},
{0, 0, 0, 89, 92},
{0, 99, 96, 95, 81}
};
void dfs(int step, int now) //当前第几号位
{if(step == 6) { //完成5个位置后, 结束递归ans = max(ans, now);return; //递归回上一个位置}//遍历for(int i = 0; i < 20; ++i) {if(book[i] == 0) { //第i号队员没被选上book[i] = 1; //标记dfs(step + 1, now + c[i][step - 1]); //递归book[i] = 0; //取消标记}}
}
int main()
{dfs(1, 0); //从1号位开始cout<<ans;return 0;
}
注意第36行step要-1,因为c[20][5]里,第几列的下标从0开始,第5列的下标是4,所以step == 5时
下标应该为4,所以-1,否则数组超限会输出491
2,读取同一目录下的文件
关于将20行6列的team.txt读取到c[20][6]这个二维数组中
的操作
#include<fstream> //ifstream读取文件
...
//ifstream打开文件,命名为infileifstream infile("team.txt"); //文件名作为参数,""括起来//读取文件每一个数字for(int i = 0; i < 20; ++i)for(int j = 0; j < 6; ++j)infile >> c[i][j]; //存储到二维数组cinfile.close(); //关闭文件
原始代码
#include<iostream>
#include<fstream> //ifstream读取文件
using namespace std;
int book[30], ans, c[20][6];
void dfs(int step, int now) //当前第几号位
{if(step == 6) { //完成5个位置后, 结束递归ans = max(ans, now);return; //递归回上一个位置}//遍历for(int i = 0; i < 20; ++i) {if(book[i] == 0) { //第i号队员没被选上book[i] = 1; //标记dfs(step + 1, now + c[i][step]); //递归book[i] = 0; //取消标记}}
}
int main()
{//ifstream打开文件,命名为infileifstream infile("team.txt"); //文件名作为参数,""括起来//读取文件每一个数字for(int i = 0; i < 20; ++i)for(int j = 0; j < 6; ++j)infile >> c[i][j]; //存储到二维数组cinfile.close(); //关闭文件dfs(1, 0); //从1号位开始cout<<ans;return 0;
}
AC 代码
#include<iostream>
using namespace std;
int main()
{cout<<490;return 0;
}
🍉🍉🍉🍉🍉🍉🍉🍉🍉🍉🍉
👊填空题总结
1,预测23年题型
做了那么多2018,2019,2020,2021,2022的填空题,2023蓝桥杯省赛的填空题是什么呢,让我们猜猜看?和2023有关的前缀和或者字符串或者模拟?
2,审题细心是关键
如果你只会模板题和暴力,那你绝对无缘国奖(虽然目前我的目标是A组省二)
首先,模板题可能出现各种变式,需要仔细观察题目,去模拟一下过程,再考虑对模板进行增删改
其次,读题不细心,导致,明明会做的,拿不到分,它让你输出A就别输出B(虽然A,B你都求出来了)
3,按行读取文件字符串,保存到字符串数组中
我先声明了string maze[30],然后将同一目录下maze.txt中的30行字符串读入maze[30]
#include<fstream>
string maze[30];
...
//读取文件数据ifstream infile("maze.txt"); //打开maze.txt文件//按行读入maze.txt文件的字符串, 保存到maze数组中for(int i = 0; i < 30; ++i)getline(infile, maze[i]);
按单个数字读取
#include<fstream> //ifstream读取文件
int c[20][6];
...
//ifstream打开文件,命名为infileifstream infile("team.txt"); //文件名作为参数,""括起来//读取文件每一个数字for(int i = 0; i < 20; ++i)for(int j = 0; j < 6; ++j)infile >> c[i][j]; //存储到二维数组cinfile.close(); //关闭文件
相关文章:

蓝桥杯C++组怒刷50道真题(填空题)
🌼深夜伤感网抑云 - 南辰Music/御小兮 - 单曲 - 网易云音乐 🌼多年后再见你 - 乔洋/周林枫 - 单曲 - 网易云音乐 18~22年真题,50题才停更,课业繁忙,有空就更,2023/3/18/23:01写下 目录 👊填…...
Shell自动化管理 for ORACLE DBA
1.自动收集每天早上9点到晚上8点之间的AWR报告。 auto_awr.sh #!/bin/bash# Set variables ORACLE_HOME/u01/app/oracle/product/12.1.0/dbhome_1 ORACLE_SIDorcl AWR_DIR/home/oracle/AWR# Set date format for file naming DATE$(date %Y%m%d%H%M%S)# Check current time - …...

Unity学习日记13(画布相关)
目录 创建画布 对画布的目标图片进行射线检测 拉锚点 UI文本框使用 按钮 按钮导航 按钮触发事件 输入框 实现单选框 下拉菜单 多选框选项加图片 创建画布 渲染模式 第一个,保持画布在最前方,画布内的内容显示优先级最高。 第二个,…...

初阶C语言:冒泡排序
冒泡排序是一种简单的排序算法,它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。1.冒泡排序关于冒泡排序我们在讲…...

带头双向循环链表
在前面我们学习了单链表,发现单链表还是有一些不够方便,比如我们要尾插,需要遍历一遍然后找到它的尾,这样时间复炸度就为O(N),现在我们引入双向带头链表就很方便了,我们先看看它的结构。通过观察,我们发现一…...

C#中的DataGridView中添加按钮并操作数据
背景:最近在项目中有需求需要在DataGridView中添加“删除”、“修改”按钮,用来对数据的操作以及显示。 在DataGridView中显示需要的按钮 首先在DataGridView中添加需要的列,此列是用来存放按钮的。 然后在代码中“画”按钮。 if (e.Column…...
WEB安全 PHP基础
WEB安全 PHP基础 PHP简述 PHP(全称:PHP:Hypertext Preprocessor,即"PHP:超文本预处理器")是一种通用开源脚本语言。 在一个php文件中可以包括以下内容: PHP 文件可包含文本、HTML、…...

基础篇:07-Nacos注册中心
1.Nacos安装部署 1.1 下载安装 nacos官网提供了安装部署教程,其下载链接指向github官网,选择合适版本即可。如访问受阻可直接使用以下最新稳定版压缩包:📎nacos-server-2.1.0.zip,后续我们也可能会更改为其他版本做更…...

端口镜像讲解
目录 端口类型 镜像方向 观察端口位置 端口镜像实现方式 流镜像 Vlan镜像 MAC镜像 配置端口镜像 配置本地观察端口 配置远程流镜像(基于流镜像) 端口镜像是指将经过指定端口的报文复制一份到另一个指定端口,便于业务监控和故障定位…...

图形视图框架QGraphicsScene(场景,概念)
QGraphicsScene 该类充当 QGraphicsItems 的容器。它与 QGraphicsView 一起使用,用于在 2D 表面上可视化图形项目,例如线条、矩形、文本甚至自定义项目。 QGraphicsScene具有的功能: 提供用管理大量数据项的高速接口传播事件到每一个图形项…...
ChatGPT 拓展资料: 强化学习-SARSA算法
强化学习是一种机器学习技术,它关注的是在特定环境中,如何最大化一个智能体(agent)的累积奖励(reward)。强化学习算法会根据当前状态和环境的反馈来选择下一个动作,不断地进行试错,从而优化智能体的行为。 SARSA是一种基于强化学习的算法,它可以用于解决马尔可夫决策…...

SpringJDBC异常抽象
前言spring会将所有的常见数据库的操作异常抽象转换成他自己的异常,这些异常的基类是DataAccessException。DataAccessException是RuntimeException的子类(运行时异常),是一个无须检测的异常,不要求代码去处理这类异常SQLErrorCodeSQLExcepti…...
我在字节的这两年
前言 作为脉脉和前端技术社区的活跃分子,我比较幸运的有了诸多面试机会并最终一路升级打怪如愿来到了这里。正式入职时间为2021年1月4日,也就是元旦后的第一个工作日。对于这一天,我印象深刻。踩着2020年的尾巴接到offer,属实是过了一个快乐…...
Button(按钮)与ImageButton(图像按钮)
今天给大家介绍的Android基本控件中的两个按钮控件,Button普通按钮和ImageButton图像按钮; 其实ImageButton和Button的用法基本类似,至于与图片相关的则和后面ImageView相同,所以本节只对Button进行讲解,另外Button是TextView的子类,所以TextView上很多属性也可以应用到B…...
Chrome插件开发-右键菜单开启页面编辑
开发一个执行js脚本改变页面DOM的Chrome插件,manifest_version版本为3。 Chrome插件基本知识 Chrome插件通常由以下几部分组成: manifest.json 该文件为必须项,其它文件都是可选的。该文件相当于插件的meta信息,包含manifest版…...

指针进阶(上)
内容小复习🐱: 字符指针:存放字符的数组 char arr1[10]; 整型数组:存放整型的数组 int arr2[5]; 指针数组:存放的是指针的数组 存放字符指针的数组(字符指针数组) char* arr3[5]; 存放整型指针的数组(整型指针数组) int* arr[6]; 下面进入学习了哦~&…...

Python每日一练(20230318)
目录 1. 排序链表 ★★ 2. 最长连续序列 ★★ 3. 扰乱字符串 ★★★ 🌟 每日一练刷题专栏 🌟 Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 1. 排序链表 给你链表的头结点 head ,请将其按 升序 …...

多层多输入的CNN-LSTM时间序列回归预测(卷积神经网络-长短期记忆网络)——附代码
目录 摘要: 卷积神经网络(CNN)的介绍: 长短期记忆网络(LSTM)的介绍: CNN-LSTM: Matlab代码运行结果: 本文Matlab代码数据分享: 摘要: 本文使用CNN-LSTM混合神经网…...

mybatis中获取参数的两种方式:${}和#{}
目录 1.#{} 2.${} 3.总结 1.#{} 本质是占位符赋值 示例及执行结果: 结论:通过执行结果可以看到,首先对sql进行了预编译处理,然后再传入参数,有效的避免了sql注入的问题,并且传参方式也比较简单…...

复制带随机指针的复杂链表
目录一、题目题目链接二、题目分析三、解题思路四、解题步骤4.1 复制结点并链接到对应原节点的后面4.2 处理复制的结点的随机指针random4.3 分离复制的链表结点和原链表结点并重新链接成为链表五、参考代码六、总结一、题目题目链接 题目链接:https://…...

SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...
云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?
大家好,欢迎来到《云原生核心技术》系列的第七篇! 在上一篇,我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在,我们就像一个拥有了一块崭新数字土地的农场主,是时…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

IT供电系统绝缘监测及故障定位解决方案
随着新能源的快速发展,光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域,IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选,但在长期运行中,例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...
是否存在路径(FIFOBB算法)
题目描述 一个具有 n 个顶点e条边的无向图,该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序,确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数,分别表示n 和 e 的值(1…...

云原生安全实战:API网关Kong的鉴权与限流详解
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关(API Gateway) API网关是微服务架构中的核心组件,负责统一管理所有API的流量入口。它像一座…...

逻辑回归暴力训练预测金融欺诈
简述 「使用逻辑回归暴力预测金融欺诈,并不断增加特征维度持续测试」的做法,体现了一种逐步建模与迭代验证的实验思路,在金融欺诈检测中非常有价值,本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...
人工智能--安全大模型训练计划:基于Fine-tuning + LLM Agent
安全大模型训练计划:基于Fine-tuning LLM Agent 1. 构建高质量安全数据集 目标:为安全大模型创建高质量、去偏、符合伦理的训练数据集,涵盖安全相关任务(如有害内容检测、隐私保护、道德推理等)。 1.1 数据收集 描…...
uniapp 实现腾讯云IM群文件上传下载功能
UniApp 集成腾讯云IM实现群文件上传下载功能全攻略 一、功能背景与技术选型 在团队协作场景中,群文件共享是核心需求之一。本文将介绍如何基于腾讯云IMCOS,在uniapp中实现: 群内文件上传/下载文件元数据管理下载进度追踪跨平台文件预览 二…...