蓝桥通关思路:
一.题型分析
代码填空题:
仅仅只需要输出问题的答案就行,不管你用什么方法实现
合理利用,表格,word,和手算, 能不编程绝不编
编程计算结果可以使用电脑自带的python的IDLE
(因为python的一些特性,pyhon在处理大数字,和日期,以及字符上会有比较好的优势)
但是对于需要大量循环结构的,还是使用c++,因为pyhon处理循环还是太慢了.
编程大题
题目会涉及到各种算法,但是一道题目通常拥有多个解法,会用这个算法的就用算法拿高分,不会的将使用模拟和暴力来解决.对于不会算法不会模拟的题,可以通过猜样例,直接输出可能的结果碰碰运气
注意:
1.c++的输入输出cin,cout虽然使用方便,但是相比于c语言的输入输出函数,性能上有较大差距,
可以通过关流操作来使cin和cout达到与c语言一样的性能.
注:c++关流 在数据量大的情况下做到与c语言输入输出相当
#define endl '\n'
std::ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
2.编译头文件可以使用万能头文件
#include<bits/stdc++.h>
3.注意数据溢出的问题
int类型大小 2^32-1 大约10^9次方
long long 类型 2^63-1 大约10^18次方
4.return 0的问题,程序末尾一定要加
5.stl里面的重要的容器:
-
vector:用于存储动态数组的容器,支持快速随机访问和动态大小调整。
vector:使用的时候记得提前分配好大概的空间,不然会导致频繁的开辟空间导致性能的下降
-
set:用于存储唯一元素的容器,元素会按照一定的顺序排列。
-
map:用于存储键值对的容器,每个键都唯一,可以通过键快速查找对应的值。
-
队列:用于实现先进先出(FIFO)的数据结构,支持在队尾插入元素,在队头删除元素。
-
二元组:用于存储两个元素的容器,可以方便地将两个值打包在一起。
-
栈:用于实现后进先出(LIFO)的数据结构,支持在栈顶插入和删除元素。
6.常用封装好的算法
排序,二分,翻转,查找
二.考察内容分析
A.枚举与模拟
枚举一般包含:模拟问题,日期判断,还有数字与组合问题.
这类题可以直接暴力枚举,但是如果样例和数据大于10^9就要考虑使用二分,不然拿不到全分.
如果不会就直接使用暴力枚举和模拟
如果枚举检查判断的操作可以不放在循环内部进行,就可以牺牲部分空间来换时间,可以通过一个bool数组来提前记录需要检查的值.
常考察的问题:
1.整数快速取余(位)
2. 日期合法判断,闰年的判断(年份能被4整除且不能被100整除,或者能被400整除)
3.利用数组拆环成链
4.最大公因数,最小公约数
5.数的分解,组合问题n!
数的分解i<j<K可以满足这个条件,然后通过n!来判断它的可能组合数量
6.字符串的拼接,子串,翻转,类型转换,查找,计数,大小写转换
7.全排列问题
8.等差数列
B.搜索与查找
1.DFS,BFS处理迷宫问题,找短最优路径
2.DFS排列组合问题
3. 判断图的连通性,岛屿问题
4.动态规划加DFS
C.思维和贪心
这个就看贪心策略的选择和递归或者循环的使用了
D.简单数论
唯一分解定理,约数定理,质数的判断,质数筛
E.字符串算法
熟练掌握字符串的使用 string 包括容器的二分查找这个非常有用
会用kmp用kmp,不会用find加迭代器
F.动态规划
分解子问题
G.数据结构
二叉树
三.算法实现整理
整数快速取余(位)
c++
while (x > 0) {
int c = x % 10;
x /= 10;
cout << c;
}
python
while date>0:
a=date%10
date//=10
#整数除法
print(a)
2.日期合法性检查
int months[13]={-1,31,28,31,30,31,30,31,31,30,31,30,31};
bool checkdays(int date){
int y=date/10000,m=date/100%100,d=date%100;
if(y%400==0||(y%4==0&&y%100!=0)) months[2]=29;
if(m<0||m>12||d<0||d>months[m]) return false;
else return true;
}
def checkdays(date):
date_str = str(date)
try:
datetime.strptime(date_str, '%Y%m%d')
return True
except ValueError:
return False
3.字符串的拼接,子串,翻转,类型转换,查找,计数,大小写转换
#include <iostream>
#include <string>
#include <algorithm>
int main() {
// 字符串拼接
std::string str1 = "Hello, ";
std::string str2 = "world!";
std::string result = str1 + str2;
std::cout << "拼接后的字符串:" << result << std::endl;
// 子串
std::string sub = result.substr(7, 5);
std::cout << "子串:" << sub << std::endl;
// 翻转
std::reverse(sub.begin(), sub.end());
std::cout << "翻转后的子串:" << sub << std::endl;
// 类型转换
int num = std::stoi(sub);
std::cout << "转换为整数:" << num << std::endl;
// 查找
size_t pos = result.find("world");
if (pos != std::string::npos) {
std::cout << "找到子串 'world',位置在:" << pos << std::endl;
}
// 计数
int count = std::count(result.begin(), result.end(), 'l');
std::cout << "'l' 的个数:" << count << std::endl;
// 大小写转换
std::transform(result.begin(), result.end(), result.begin(), ::toupper);
std::cout << "大写转换后的字符串:" << result << std::endl;
// 字符串计数
int countSubstring(const std::string& str, const std::string& sub) {
int count = 0;
size_t pos = 0;
while ((pos = str.find(sub, pos)) != std::string::npos) {
count++;
pos += sub.length();
}
return count;
}
return 0;
}
str1="file"
str2="edit"
#拼接
str3=str1+str2
print(str3)
#子串
str4=str3[1:5]
print(str4)
#翻转
str5=str2[::-1]
print(str5)
#查找
pos=str3.find("it")
if pos != -1:
print(pos)
#计数
count=str3.count("i")
count2=str3.count("il")
print(count,count2)
#类型转换
year="2001"
date=int(year)
#替换
str11=str1.replace("file","1")
print(str11)
利用数组下标的转换,可以将一维数组拓展为环状结构
c++
#include<iostream>
using namespace std;
int main(){
int num[5]={1,2,3,4,5};
int count=10;
for(int pow=0;pow<5;pow++){
cout<<num[pow];//通过下标扩展为环
if(pow==4) pow=-1;
count--;
if(count<0) break;
}
return 0;
}
求最大公约数 最小公倍数的函数
c++
#include <algorithm>
__gcd(i,k); //返回i与k的最大公约数;
a*b/__gcd(a,b); //a与b的最小公倍数
python
def gcd(a, b):
if b == 0:
return a
return gcd(b, a % b)
def lcm(a, b):
return a // gcd(a, b) * b
数的分解i<j<K可以满足这个条件,然后通过n!来判断它的可能组合。
对于一些固定标记flage可以先定义赋值,然后直接利用数组下标进行判断加快运算速度
全排列问题
// 全排列数组
std::vector<int> arr = {1, 2, 3};
std::sort(arr.begin(), arr.end()); // 首先对数组进行排序
do {
for (int num : arr) {
std::cout << num << " ";
}
std::cout << std::endl;
} while(std::next_permutation(arr.begin(), arr.end()));
// 全排列字符串
std::string str = "abc";
std::sort(str.begin(), str.end()); // 首先对字符串进行排序
do {
std::cout << str << std::endl;
} while(std::next_permutation(str.begin(), str.end()));
return 0;
}
from itertools import permutations
# 对字符串进行全排列
s = "abc"
perms_str = [''.join(p) for p in permutations(s)]
print(perms_str)
# 对数组进行全排列
arr = [1, 2, 3]
perms_arr = list(permutations(arr))
print(perms_arr)
深度优先搜索 (图)
c++递归模版输出最短路径和路径内容
#include<bits/stdc++.h>
using namespace std;
char map1[101][101];//地图信息
bool vic[101][101];//是否走过
pair<int,int> st,ed;//起点终点
int n,m;//地图大小
vector<pair<int, int>> minPath; // 最短路径
int minstep =0x3f3f;//最小步数
int vc[4][2]={{1,0},{0,1},{-1,0},{0,-1}};//方向记录
void dfs(int x,int y,int step, vector<pair<int, int>> path){
if(x==ed.first&&y==ed.second) {
if(step < minstep){
minstep = step;
minPath = path;
}
return;
}
if(step >= minstep) return; // 当前步数已经超过最小步数,无需继续搜索
int tx=0,ty=0;
for (int i = 0; i < 4; i++) {
tx = x + vc[i][0];
ty = y + vc[i][1];
if (tx < 1 || tx > n || ty < 1 || ty > m) continue; // 检查越界
if (map1[tx][ty] == '0' && vic[tx][ty] == 0) { // 未走过且非障碍
vic[tx][ty] = 1;//标记走过
path.push_back({tx, ty}); // 将当前位置加入路径
dfs(tx, ty, step + 1, path);//递归
vic[tx][ty] = 0;//回退
path.pop_back(); // 回退路径
}
}
}
int main(){
cin>>n>>m;
for(int i =1;i<=n;i++)
for(int j =1;j<=m;j++){
cin>>map1[i][j];
}
cin>>st.first>>st.second;
cin>>ed.first>>ed.second;
vic[st.first][st.second] = 1; // 标记起点为已走过
vector<pair<int, int>> path = {st}; // 起点加入路径
dfs(st.first,st.second,0, path);
cout<<"最短步数:"<<minstep<<endl;
cout<<"最短路径:";
for(auto p : minPath){
cout<<"("<<p.first<<","<<p.second<<") ";
}
cout<<endl;
return 0;
}
显示栈实现DFS
#include<bits/stdc++.h>
using namespace std;
char map1[101][101];//地图信息
bool vic[101][101];//是否走过
pair<int,int> st,ed;//起点终点
int n,m;//地图大小
int minstep =0x3f3f;//最小步数
int vc[4][2]={{1,0},{0,1},{-1,0},{0,-1}};//方向记录
vector<pair<int, int>> shortestPath; // 记录最短路径
struct Node {
int x, y, step;
vector<pair<int, int>> path; // 记录路径
Node(int _x, int _y, int _step, vector<pair<int, int>> _path) : x(_x), y(_y), step(_step), path(_path) {}
};
void dfs(){
stack<Node> s;
s.push(Node(st.first, st.second, 0, {st}));
while (!s.empty()) {
Node cur = s.top();
s.pop();
if(cur.x == ed.first && cur.y == ed.second) {
if (cur.step < minstep) {
minstep = cur.step; // 更新最小步数
shortestPath = cur.path; // 更新最短路径
}
continue;
}
if(cur.step >= minstep) continue; // 当前步数已经超过最小步数,无需继续搜索
for (int i = 0; i < 4; i++) {
int tx = cur.x + vc[i][0];
int ty = cur.y + vc[i][1];
if (tx < 1 || tx > n || ty < 1 || ty > m) continue; // 检查越界
if (map1[tx][ty] == '0' && vic[tx][ty] == 0) { // 未走过且非障碍
vic[tx][ty] = 1;//标记走过
vector<pair<int, int>> newPath = cur.path;
newPath.push_back({tx, ty});
s.push(Node(tx, ty, cur.step + 1, newPath));//入栈
vic[tx][ty] = 0;//回退
}
}
}
}
int main(){
cin>>n>>m;
for(int i =1;i<=n;i++)
for(int j =1;j<=m;j++){
cin>>map1[i][j];
}
cin>>st.first>>st.second;
cin>>ed.first>>ed.second;
dfs();
cout<<"最短步数为:"<<minstep<<endl;
cout<<"最短路径为:";
for (auto point : shortestPath) {
cout<<"("<<point.first<<","<<point.second<<") ";
}
cout<<endl;
return 0;
}
广度优先BFS问题
#include <bits/stdc++.h>
using namespace std;
int map1[101][101], vic[101][101], dis[101][101];
int n, m;
int vc[4][2] = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}};
pair<int, int> parent[101][101];
int bfs(queue<pair<int, int>> smap) {
while (!smap.empty()) {
pair<int, int> cur = smap.front();//取出队首节点
smap.pop();//队首节点出队
int x = cur.first;
int y = cur.second;
if(x==n&&y==m) return dis[x][y];
int tx=0,ty=0;
for(int i =0;i<4;i++){
tx=x+vc[i][0];
ty=y+vc[i][1];
if(tx<1||tx>n||ty<1||ty>m||map1[tx][ty]==1||vic[tx][ty]==1) continue;
else{
smap.push({tx,ty});
vic[tx][ty]=1;
dis[tx][ty]=dis[x][y]+1;
parent[tx][ty]={x,y};
}
}
}
return -1;
}
void printPath(int x, int y) {
if (x == 1 && y == 1) {
cout << "(1, 1) ";
return;
}
printPath(parent[x][y].first, parent[x][y].second);
cout << "(" << x << ", " << y << ") ";
}
int main() {
cin >> n >> m;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
cin >> map1[i][j];
}
queue<pair<int, int>> smap;
smap.push({1, 1});
int minstep = bfs(smap);
cout<<minstep<<endl;
printPath(parent[n][m].first,parent[n][m].second);
return 0;
}
sort这个排序实在太棒了
bool compare(const cklt& n, const cklt& m) {
// 首先比较 b/a 的比值
if (n.b * m.a > m.b * n.a) {
return true; // n.b/n.a > m.b/m.a
} else if (n.b * m.a < m.b * n.a) {
return false; // n.b/n.a < m.b/m.a
} else {
// 如果比值相等,则比较 a 的值
return n.a < m.a; // a 越小,排序越靠前
}
}
//将除法比较变成了乘法比较。(防止出现除数为零导致程序崩溃)