速记-蓝桥杯c++组

蓝桥通关思路:

一.题型分析

代码填空题:

仅仅只需要输出问题的答案就行,不管你用什么方法实现

      合理利用,表格,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 越小,排序越靠前  
    }  
}
//将除法比较变成了乘法比较。(防止出现除数为零导致程序崩溃)

  • 21
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值