0基础蓝桥杯50天备赛(算法篇)

文章详细介绍了暴力枚举、深度优先搜索(DFS)在全排列、进制问题、最大连通、环检测、正则问题以及并查集、排序算法(如sort函数)和堆/优先队列等IT技术的应用实例,展示了编程中常用的数据结构和算法技巧。
摘要由CSDN通过智能技术生成

代码并非全部为本人原创,仅提供整理作用;

不是蓝桥杯的题目会提供全部内容;

一. 暴力枚举

1.直接枚举( for+if )

2.递归枚举法(dfs)

模板:

void dfs(参数){

if(终止条件){搜集结果;return;}

for(单层所有元素){

(不可使用的元素剪枝)continue;

标记;

递归(参数+1);

取消标记;}   }

如果要不断比较,更新结果则要不断回溯  vis[i]=0;

地图一般不回溯;

(1)全排列:给定一个数字n,请按照字典序输出排列[1,2,...,n]的全排列。

dfs里for遍历完之后回到上一个dfs的位置。

#include<bits/stdc++.h> 
using namespace std;
const int N=15;
int a[N];
bool vis[N];
void dfs(int dep,int n){
	if(dep==n+1){
		for(int i=1;i<=n;i++)cout<<a[i]<<" ";
		cout<<endl;
		return;
	}
	for(int i=1;i<=n;i++){
		if(vis[i])continue;
		vis[i]=1;
		a[dep]=i;
		dfs(dep+1,n);
		vis[i]=0;
	}
}
int main(){
	int n;cin>>n;
	dfs(1,n);
	return 0;
}

最大数字:进制问题/贪心/回溯 

#include <bits/stdc++.h>
using namespace std;
string n;
long long ans; 
int a,b;
void dfs(int x,long long an){   
    int t=n[x]-'0';    
    if(!n[x]){  ans=max(ans,an);
	              return;}        
        int c=min(a,9-t);
        a-=c;
        dfs(x+1,an*10+t+c);
        a+=c;
        if(b>t){
            b=b-t-1;
            dfs(x+1,an*10+9);
            b=b+t+1;
        }
    }

int main(){
    cin>>n>>a>>b;
    dfs(0,0); 
    cout<<ans;
    return 0;
}

  (2)   最大连通: DFS与连通性

#include<bits/stdc++.h>
using namespace std;
char g[35][65];
int a[4][2]={0,1,0,-1,1,0,-1,0};
int vis[35][65]={0};
int ans=0;
int sum=0;
void dfs(int x,int y){
	if(x<0||x>29||y<0||x>59||g[x][y]!='1'||vis[x][y])return;
	sum++;
	vis[x][y]=1;
	for(int i=0;i<4;i++){
		int tx=x+a[i][0];
		int ty=y+a[i][1];
		if(tx>=0&&ty>=0&&tx<=29&&ty<=59&&g[tx][ty]=='1'&&vis[tx][ty]==0){
		dfs(tx,ty);}
	}
	ans= max(ans,sum);
}
int main(){
  for(int i=0;i<30;i++){
    for(int j=0;j<60;j++){
      cin>>g[i][j];
    }
  }
  for(int i=0;i<30;i++){
    for(int j=0;j<60;j++){
      sum=0;
      if(g[i][j]=='1'){//不是需要的元素不进入if;
      	dfs(i,j);
	  }
    }
  }
  cout<<ans;
	return 0;
}

(3)小朋友崇拜圈:闭环问题

(有1234隐形序列)

#include <iostream>
using namespace std;
int a[100005];
int vis[100005];
int m,t;
void dfs(int x,int ans){
	if(vis[x]){if(x==t){//第一个回到的点是自己,则为环;
		if(ans>m)m=ans;//如果为环,则进行大小判断传入结果,无则直接return;
		}return;
	}
	vis[x]=1;//标记;
	dfs(a[x],ans+1);//a[x]为指向的元素,ans为已走的步数;
	vis[x]=0;//回溯;
}
int main(){
	int n;cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];//i表示自己,a[i]表示指向的元素;
	}
	for(int i=1;i<=n;i++){
		t=i;//用临时变量保存自己,该变量为全局变量;
		dfs(i,0);
	}cout<<m;
  return 0;
}

(4)正则问题:分组计数用dfs

#include <bits/stdc++.h>
using namespace std;
string s;
int k=0;
int dfs(){
  int res=0;//递归的res不断初始化为0;
  while(k<s.size()){
     if(s[k]=='('){
       k++;//索引先行;
       res += dfs();//只要括号未结束就会一直在递归中,直到输出结果;
       k++;//跳过')',使得k>=s.size,结束循环;
     }
     else if(s[k]=='|'){
       k++;
       res=max(res,dfs());
     }
     else if(s[k]==')'){
       break;//break跳出函数,执行下一句,return出dfs的结果;
     }
     else {
       k++;
       res++;//什么都没有直接res+1;
     }
  }
  return res;
}
int main()
{
  cin>>s;
  cout<<dfs()<<endl;
  return 0;
}

二.并查集

(1)无优化:

#include<bits/stdc++.h> 
using namespace std;
typedef long long ll;
const int N=100009;
int pre[N];//父节点(根节点)
int root(int x){//用递归查找根节点
	return pre[x]==x?x:root(pre[x]);
}
void merge (int x,int y){//用一条节点的根节点连到另一个节点,表合并操作
	x=root(x);y=root(y);
	if(x==y)return;//若已经同根相连,即已连通,return即可
	pre[x]=y;//pre[y]=x;两个点都可
}
void solve(){
	int n,m;cin>>n>>m;
	for(int i=1;i<=n;++i)pre[i]=i;//初始化:自己是自己的根节点
	while(m--){
		int op,x,y;cin>>op>>x>>y;
		if(op==1)merge(x,y);
		else cout<<(root(x)==root(y)?"Y":"N")<<"\n";//用三目运算符输出需用()
	}
} 
int main(){
 ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);//取消同步流,提高速度,未优化的速度极慢
	int _ =1;
	while( _ --)solve();
	return 0;
}

【一】+【二】+邻接表:

发现环:

#include<bits/stdc++.h>
using namespace std;
int p[100050],vis[100050],ans[100050];
int n,a,b;
int s,en;//dfs (start end)
vector<int>e[100050];//edge
int root(int x){return p[x]==-1?x:p[x]=root(p[x]);}
void pr(int step)//排序输出
{
    sort(ans+1,ans+1+step);//ans[0]=0; 
    for(int i=1;i<=step;i++)cout<<ans[i]<<" ";
}
void dfs(int x,int step)
{
	vis[x]=1;//sign
    ans[step]=x;
    if(x==en){pr(step);return;}
    for(int i=0;i<e[x].size();i++){
        if(!vis[e[x][i]])dfs(e[x][i],step+1);}
		//4的邻接点是2,2不满足if,
		//循环结束回到上一节点2的另一种可能1,同一层step的结果覆盖; 
} 
int main()
{
    memset(p,-1,sizeof(p));//初始化 
    cin>>n;
    while(n--){
        cin>>a>>b;
        if(root(a)==root(b))s=a,en=b;
        else {
            p[root(b)]=a;//merge
            e[a].push_back(b);//edge
            e[b].push_back(a);
        }
    }
    dfs(s,1);
    return 0;
}

三.排序算法

1.sort函数

数组和指针用sort(a+n,a+m);//end要比实际多出一位;

STL容器用迭代器sort(a.begin(),a.end());

#include <bits/stdc++.h>
using namespace std;
int a[500086];
bool cmp(int x,int y){
  return x>y;
}
//struct cmp2(){
//bool operator()(char a,char b){
//return a>b;}
int main()
{
  int n;
  cin>>n;
  for(int i=1;i<=n;i++)cin>>a[i];
  sort(a+1,a+n+1);//不写默认升序;
  for(int i=1;i<=n;i++)cout<<a[i]<<" ";
  cout<<"\n";
  sort (a+1,a+n+1,cmp);
//sort (a+1,a+n+1,cmp2());struct要加括号;
//sort (a+1,a+n+1,greater());直接写STL的库函数,降序函数;
  for(int i=1;i<=n;i++)cout<<a[i]<<" ";
  return 0;
}

四.数学算法

你不干?有的是帕鲁干!(小白赛);

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
int main(){
	long long  n,x,a,b,k;
	cin>>n; 
	while(n--){
		cin>>x;
		if(x%8==0 && x>0){
			cout<<"Yes"<<endl; 
			k=x/4;
			a=k-1;
			b=k+1;
			cout<<a<<" " <<b<<endl;
		}else cout<<"No" <<endl;
	}return 0;
}

五.堆/优先队列

#include<bits/stdc++.h>
using namespace std;
int main(){
	int q;cin>>q;
	priority_queue<int>pq;
	long long x,sum=0;
	while(q--){
		int op;cin>>op;
		if(op==1){
			cin>>x;
			sum+=x;
			pq.push(x);
		}
		else if(op==2){
			if(pq.size()){
			sum-=pq.top();
			pq.pop();
		}}
	}cout<<sum<<endl;
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值